summaryrefslogtreecommitdiff
path: root/libjava/classpath/gnu/java/awt/peer
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/gnu/java/awt/peer
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/classpath/gnu/java/awt/peer')
-rw-r--r--libjava/classpath/gnu/java/awt/peer/ClasspathDesktopPeer.java301
-rw-r--r--libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java865
-rw-r--r--libjava/classpath/gnu/java/awt/peer/EmbeddedWindowPeer.java47
-rw-r--r--libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java461
-rw-r--r--libjava/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java155
-rw-r--r--libjava/classpath/gnu/java/awt/peer/KDEDesktopPeer.java135
-rw-r--r--libjava/classpath/gnu/java/awt/peer/NativeEventLoopRunningEvent.java58
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/AsyncImage.java283
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java538
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java2176
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java428
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java355
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java941
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java122
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java630
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java545
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java156
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java172
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java785
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java99
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java362
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java93
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkCanvasPeer.java60
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java74
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java255
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java142
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java436
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java129
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java920
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java138
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkCursor.java72
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkDialogPeer.java63
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkEmbeddedWindowPeer.java73
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java229
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java254
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java145
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java541
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java169
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java102
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java187
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMainThread.java188
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java113
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java104
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java116
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java126
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java65
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java67
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java68
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java111
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java92
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkSelection.java675
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java223
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java200
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java766
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java207
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java437
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java325
-rw-r--r--libjava/classpath/gnu/java/awt/peer/gtk/package.html46
-rw-r--r--libjava/classpath/gnu/java/awt/peer/headless/HeadlessGraphicsEnvironment.java118
-rw-r--r--libjava/classpath/gnu/java/awt/peer/headless/HeadlessToolkit.java385
-rw-r--r--libjava/classpath/gnu/java/awt/peer/package.html46
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/MainQtThread.java84
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/NativeWrapper.java43
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QMatrix.java72
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QPainterPath.java140
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QPen.java70
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtAudioClip.java110
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtButtonPeer.java75
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtCanvasPeer.java65
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtCheckboxPeer.java111
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtChoicePeer.java93
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtComponentGraphics.java120
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtComponentPeer.java834
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtContainerPeer.java112
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtDialogPeer.java73
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtEmbeddedWindowPeer.java64
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtFileDialogPeer.java83
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtFontMetrics.java125
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtFontPeer.java197
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtFramePeer.java164
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtGraphics.java714
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtGraphicsEnvironment.java105
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtImage.java641
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtImageConsumer.java147
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtImageDirectGraphics.java145
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtImageGraphics.java139
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtLabelPeer.java62
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtListPeer.java188
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtMenuBarPeer.java101
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtMenuComponentPeer.java94
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtMenuItemPeer.java100
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtMenuPeer.java149
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtPanelPeer.java56
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtPopupMenuPeer.java76
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtRepaintThread.java156
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtScreenDevice.java115
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtScreenDeviceConfiguration.java145
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtScrollPanePeer.java90
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtScrollbarPeer.java80
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtTextAreaPeer.java179
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtTextFieldPeer.java159
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java470
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtVolatileImage.java434
-rw-r--r--libjava/classpath/gnu/java/awt/peer/qt/QtWindowPeer.java105
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java261
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingCanvasPeer.java64
-rwxr-xr-xlibjava/classpath/gnu/java/awt/peer/swing/SwingCheckboxPeer.java256
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java99
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java1136
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java378
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingFramePeer.java197
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java242
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingListPeer.java364
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingMenuBarPeer.java295
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingMenuItemPeer.java157
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingMenuPeer.java284
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java67
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingTextAreaPeer.java487
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java411
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java181
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java99
-rw-r--r--libjava/classpath/gnu/java/awt/peer/swing/package.html71
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/GLGraphics.java134
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/KeyboardMapping.java419
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/PixmapVolatileImage.java185
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XDialogPeer.java61
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XEventPump.java486
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XFontPeer.java770
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XFramePeer.java145
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XGraphics2D.java508
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XGraphicsConfiguration.java200
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XGraphicsDevice.java200
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XGraphicsEnvironment.java203
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XImage.java178
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XToolkit.java667
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/XWindowPeer.java303
-rw-r--r--libjava/classpath/gnu/java/awt/peer/x/ZPixmapDataBuffer.java67
137 files changed, 35034 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/java/awt/peer/ClasspathDesktopPeer.java b/libjava/classpath/gnu/java/awt/peer/ClasspathDesktopPeer.java
new file mode 100644
index 000000000..fd4f498aa
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/ClasspathDesktopPeer.java
@@ -0,0 +1,301 @@
+/* ClasspathDesktopPeer.java -- Offers a concrete implementation for DesktopPeer
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+package gnu.java.awt.peer;
+
+import java.awt.AWTPermission;
+import java.awt.Desktop.Action;
+import java.awt.peer.DesktopPeer;
+
+import java.io.File;
+import java.io.IOException;
+
+import java.net.URI;
+
+import java.util.prefs.Preferences;
+
+/**
+ * Offers a common implementation for the Desktop peers, that enables
+ * access to default system application within java processes.
+ *
+ * @author Mario Torre <neugens@limasoftware.net>
+ */
+public class ClasspathDesktopPeer
+ implements DesktopPeer
+{
+ /** This is the fallback browser, if no desktop was detected. */
+ protected static final String _DEFAULT_BROWSER = "firefox";
+
+ /** gnu.java.awt.peer.Desktop.html.command */
+ protected static final String _BROWSE = "html";
+
+ /** gnu.java.awt.peer.Desktop.mail.command */
+ protected static final String _MAIL = "mail";
+
+ /** gnu.java.awt.peer.Desktop.edit.command */
+ protected static final String _EDIT = "edit";
+
+ /** gnu.java.awt.peer.Desktop.print.command */
+ protected static final String _PRINT = "print";
+
+ /** gnu.java.awt.peer.Desktop.open.command */
+ protected static final String _OPEN = "open";
+
+ /** */
+ protected static final KDEDesktopPeer kde = new KDEDesktopPeer();
+
+ /** */
+ protected static final GnomeDesktopPeer gnome = new GnomeDesktopPeer();
+
+ /** */
+ protected static final ClasspathDesktopPeer classpath =
+ new ClasspathDesktopPeer();
+
+ /**
+ * Preference subsystem. Packagers and users can override the default
+ * behaviour of this class via preferences and system properties.
+ */
+ protected Preferences prefs =
+ Preferences.userNodeForPackage(ClasspathDesktopPeer.class).node("Desktop");
+
+ /**
+ * @param target
+ */
+ protected ClasspathDesktopPeer()
+ {
+ /* nothing to do */
+ }
+
+ public boolean isSupported(Action action)
+ {
+ String check = null;
+
+ switch(action)
+ {
+ case BROWSE:
+ check = _BROWSE;
+ break;
+
+ case MAIL:
+ check = _MAIL;
+ break;
+
+ case EDIT:
+ check = _EDIT;
+ break;
+
+ case PRINT:
+ check = _PRINT;
+ break;
+
+ case OPEN: default:
+ check = _OPEN;
+ break;
+ }
+
+ return this.supportCommand(check);
+ }
+
+ public void browse(URI url) throws IOException
+ {
+ checkPermissions();
+
+ String browser = getCommand(_BROWSE);
+
+ if (browser == null)
+ throw new UnsupportedOperationException();
+
+ browser = browser + " " + url.toString();
+
+ Runtime.getRuntime().exec(browser);
+ }
+
+ public void edit(File file) throws IOException
+ {
+ checkPermissions(file, false);
+
+ String edit = getCommand(_EDIT);
+
+ if (edit == null)
+ throw new UnsupportedOperationException();
+
+ edit = edit + " " + file.getAbsolutePath();
+ Runtime.getRuntime().exec(edit);
+ }
+
+ public void mail(URI mailtoURL) throws IOException
+ {
+ checkPermissions();
+
+ String scheme = mailtoURL.getScheme();
+ if (scheme == null || !scheme.equalsIgnoreCase("mailto"))
+ throw new IllegalArgumentException("URI Scheme not of type mailto");
+
+ String mail = getCommand(_MAIL);
+
+ if (mail == null)
+ throw new UnsupportedOperationException();
+
+ mail = mail + " " + mailtoURL.toString();
+
+ Runtime.getRuntime().exec(mail);
+ }
+
+ public void mail() throws IOException
+ {
+ checkPermissions();
+
+ String mail = getCommand(_MAIL);
+
+ if (mail == null)
+ throw new UnsupportedOperationException();
+
+ Runtime.getRuntime().exec(mail);
+ }
+
+ public void open(File file) throws IOException
+ {
+ checkPermissions(file, true);
+
+ String open = getCommand(_OPEN);
+
+ if (open == null)
+ throw new UnsupportedOperationException();
+
+ open = open + " " + file.getAbsolutePath();
+ Runtime.getRuntime().exec(open);
+ }
+
+ public void print(File file) throws IOException
+ {
+ checkPrintPermissions(file);
+
+ String print = getCommand(_PRINT);
+
+ if (print == null)
+ throw new UnsupportedOperationException();
+
+ print = print + " " + file.getAbsolutePath();
+ Runtime.getRuntime().exec(print);
+ }
+
+ protected String getCommand(String action)
+ {
+ // check if a system property exist
+ String command =
+ System.getProperty("gnu.java.awt.peer.Desktop." + action + ".command");
+
+ // otherwise, get it from preferences, if any
+ if (command == null)
+ {
+ command = prefs.node(action).get("command", null);
+ }
+
+ return command;
+ }
+
+ /**
+ * Note: Checks for AWTPermission("showWindowWithoutWarningBanner") only.
+ */
+ protected void checkPermissions()
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new AWTPermission("showWindowWithoutWarningBanner"));
+ }
+ }
+
+ /**
+ * Calls checkPermissions() and checks for SecurityManager.checkRead()
+ * and, if readOnly is false, for SecurityManager.checkWrite()
+ */
+ protected void checkPermissions(File file, boolean readOnly)
+ {
+ checkPermissions();
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkRead(file.toString());
+ if (!readOnly) sm.checkWrite(file.toString());
+ }
+ }
+
+ /**
+ * Calls checkPermissions(file, true) and checks for
+ * SecurityManager.checkPrintJobAccess()
+ */
+ protected void checkPrintPermissions(File file)
+ {
+ checkPermissions(file, true);
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPrintJobAccess();
+ }
+ }
+
+ /**
+ * @param check
+ * @return
+ */
+ protected boolean supportCommand(String check)
+ {
+ return ((this.getCommand(check) != null) ? true : false);
+ }
+
+ /**
+ * @return
+ */
+ public static DesktopPeer getDesktop()
+ {
+ // check if we are under Gnome or KDE or anything else
+ String desktopSession = System.getenv("GNOME_DESKTOP_SESSION_ID");
+ if (desktopSession == null)
+ {
+ desktopSession = System.getenv("KDE_FULL_SESSION");
+ if (desktopSession != null)
+ return kde;
+ }
+ else
+ {
+ return gnome;
+ }
+
+ // revert to this class for default values
+ return classpath;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java b/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java
new file mode 100644
index 000000000..96677a4af
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/ClasspathFontPeer.java
@@ -0,0 +1,865 @@
+/* ClasspathFontPeer.java -- Font peer used by GNU Classpath.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer;
+
+import gnu.java.awt.ClasspathToolkit;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Toolkit;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.LineMetrics;
+import java.awt.font.TextAttribute;
+import java.awt.font.TransformAttribute;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.peer.FontPeer;
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * A peer for fonts that are used inside Classpath. The purpose of
+ * this interface is to abstract from platform-specific font handling
+ * in the Classpath implementation of java.awt.Font and related
+ * classes.
+ *
+ * <p><b>State kept by the peer:</b> a peer is generated for each Font
+ * object in the default implementation. If you wish to share peers between
+ * fonts, you will need to subclass both ClasspathFontPeer and
+ * {@link ClasspathToolKit}.</p>
+ *
+ * <p><b>Thread Safety:</b> Methods of this interface may be called
+ * from arbitrary threads at any time. Implementations of the
+ * <code>ClasspathFontPeer</code> interface are required to perform
+ * the necessary synchronization.</p>
+ *
+ * @see java.awt.Font#getPeer
+ * @see java.awt.Toolkit#getFontPeer
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Graydon Hoare (graydon@redhat.com)
+ */
+public abstract class ClasspathFontPeer
+ implements FontPeer
+{
+
+ /*************************************************************************/
+
+ /*
+ * Instance Variables
+ */
+
+ /**
+ * The 3 names of this font. all fonts have 3 names, some of which
+ * may be equal:
+ *
+ * logical -- name the font was constructed from
+ * family -- a designer or brand name (Helvetica)
+ * face -- specific instance of a design (Helvetica Regular)
+ *
+ * @see isLogicalFontName
+ */
+
+ protected String logicalName;
+ protected String familyName;
+ protected String faceName;
+
+ /**
+ * The font style, which is a combination (by OR-ing) of the font style
+ * constants PLAIN, BOLD and ITALIC, in this class.
+ */
+ protected int style;
+
+ /**
+ * The font point size. A point is 1/72 of an inch.
+ */
+ protected float size;
+
+ /**
+ * The affine transformation the font is currently subject to.
+ */
+ protected AffineTransform transform;
+
+ static class LRUCache<K,V> extends LinkedHashMap<K,V>
+ {
+ int max_entries;
+ public LRUCache(int max)
+ {
+ super(max, 0.75f, true);
+ max_entries = max;
+ }
+ protected boolean removeEldestEntry(Map.Entry eldest)
+ {
+ return size() > max_entries;
+ }
+ }
+
+ private static LRUCache<AffineTransform,TransformAttribute> transCache =
+ new LRUCache<AffineTransform,TransformAttribute>(50);
+
+ protected static ClasspathToolkit tk()
+ {
+ return (ClasspathToolkit)(Toolkit.getDefaultToolkit ());
+ }
+
+ /*
+ * Confusingly, a Logical Font is a concept unrelated to
+ * a Font's Logical Name.
+ *
+ * A Logical Font is one of 6 built-in, abstract font types
+ * which must be supported by any java environment: SansSerif,
+ * Serif, Monospaced, Dialog, and DialogInput.
+ *
+ * A Font's Logical Name is the name the font was constructed
+ * from. This might be the name of a Logical Font, or it might
+ * be the name of a Font Face.
+ */
+
+ protected static boolean isLogicalFontName(String name)
+ {
+ String uname = name.toUpperCase ();
+ return (uname.equals ("SANSSERIF") ||
+ uname.equals ("SERIF") ||
+ uname.equals ("MONOSPACED") ||
+ uname.equals ("DIALOG") ||
+ uname.equals ("DIALOGINPUT") ||
+ uname.equals ("DEFAULT"));
+ }
+
+ protected static String logicalFontNameToFaceName (String name)
+ {
+ String uname = name.toUpperCase ();
+ if (uname.equals("SANSSERIF"))
+ return "Helvetica";
+ else if (uname.equals ("SERIF"))
+ return "Times";
+ else if (uname.equals ("MONOSPACED"))
+ return "Courier";
+ else if (uname.equals ("DIALOG"))
+ return "Helvetica";
+ else if (uname.equals ("DIALOGINPUT"))
+ return "Helvetica";
+ else if (uname.equals ("DEFAULT"))
+ return "Dialog.plain";
+ else
+ return "Helvetica";
+ }
+
+ protected static String faceNameToFamilyName (String name)
+ {
+ return name;
+ }
+
+ public static void copyStyleToAttrs (int style, Map attrs)
+ {
+ if ((style & Font.BOLD) == Font.BOLD)
+ attrs.put (TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
+ else
+ attrs.put (TextAttribute.WEIGHT, TextAttribute.WEIGHT_REGULAR);
+
+ if ((style & Font.ITALIC) == Font.ITALIC)
+ attrs.put (TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
+ else
+ attrs.put (TextAttribute.POSTURE, TextAttribute.POSTURE_REGULAR);
+ }
+
+ protected static void copyFamilyToAttrs (String fam, Map attrs)
+ {
+ if (fam != null)
+ attrs.put (TextAttribute.FAMILY, fam);
+ }
+
+ public static void copySizeToAttrs (float size, Map attrs)
+ {
+ attrs.put (TextAttribute.SIZE, new Float (size));
+ }
+
+ protected static void copyTransformToAttrs (AffineTransform trans, Map attrs)
+ {
+ if (trans != null)
+ {
+ TransformAttribute ta;
+ synchronized(transCache)
+ {
+ ta = transCache.get(trans);
+ if (ta == null)
+ {
+ ta = new TransformAttribute(trans);
+ transCache.put(trans, ta);
+ }
+ }
+ attrs.put(TextAttribute.TRANSFORM, ta);
+ }
+ }
+
+
+ protected void setStandardAttributes (String name, String family, int style,
+ float size, AffineTransform trans)
+ {
+ this.logicalName = name;
+
+ if (isLogicalFontName (name))
+ this.faceName = logicalFontNameToFaceName (name);
+ else
+ this.faceName = name;
+
+ if (family != null)
+ this.familyName = family;
+ else
+ this.familyName = faceNameToFamilyName (faceName);
+
+ this.style = style;
+ this.size = size;
+ this.transform = trans;
+ }
+
+
+ protected void setStandardAttributes (String name, Map attribs)
+ {
+ String family = this.familyName;
+ AffineTransform trans = this.transform;
+ float size = this.size;
+ int style = this.style;
+
+ if (attribs.containsKey (TextAttribute.FAMILY))
+ family = (String) attribs.get (TextAttribute.FAMILY);
+
+ if (name == null)
+ name = "Default";
+
+ if (attribs.containsKey (TextAttribute.WEIGHT))
+ {
+ Float weight = (Float) attribs.get (TextAttribute.WEIGHT);
+ if (weight.floatValue () >= TextAttribute.WEIGHT_BOLD.floatValue ())
+ style += Font.BOLD;
+ }
+
+ if (attribs.containsKey (TextAttribute.POSTURE))
+ {
+ Float posture = (Float) attribs.get (TextAttribute.POSTURE);
+ if (posture.floatValue () >= TextAttribute.POSTURE_OBLIQUE.floatValue ())
+ style += Font.ITALIC;
+ }
+
+ if (attribs.containsKey (TextAttribute.SIZE))
+ {
+ Float sz = (Float) attribs.get (TextAttribute.SIZE);
+ size = sz.floatValue ();
+
+ // Pango doesn't accept 0 as a font size.
+ if (size < 1)
+ size = 1;
+ }
+ else
+ size = 12;
+
+ if (attribs.containsKey (TextAttribute.TRANSFORM))
+ {
+ TransformAttribute ta = (TransformAttribute)
+ attribs.get(TextAttribute.TRANSFORM);
+ trans = ta.getTransform ();
+ }
+
+ setStandardAttributes (name, family, style, size, trans);
+ }
+
+ protected void getStandardAttributes (Map attrs)
+ {
+ copyFamilyToAttrs (this.familyName, attrs);
+ copySizeToAttrs (this.size, attrs);
+ copyStyleToAttrs (this.style, attrs);
+ copyTransformToAttrs (this.transform, attrs);
+ }
+
+
+ /* Begin public API */
+
+ public ClasspathFontPeer (String name, Map attrs)
+ {
+ setStandardAttributes (name, attrs);
+ }
+
+ public ClasspathFontPeer (String name, int style, int size)
+ {
+ setStandardAttributes (name, (String)null, style,
+ (float)size, (AffineTransform)null);
+ }
+
+ /**
+ * Implementation of {@link Font#getName}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public String getName (Font font)
+ {
+ return logicalName;
+ }
+
+ /**
+ * Implementation of {@link Font#getFamily()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public String getFamily (Font font)
+ {
+ return familyName;
+ }
+
+ /**
+ * Implementation of {@link Font#getFamily(Locale)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public String getFamily (Font font, Locale lc)
+ {
+ return familyName;
+ }
+
+ /**
+ * Implementation of {@link Font#getFontName()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public String getFontName (Font font)
+ {
+ return faceName;
+ }
+
+ /**
+ * Implementation of {@link Font#getFontName(Locale)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public String getFontName (Font font, Locale lc)
+ {
+ return faceName;
+ }
+
+ /**
+ * Implementation of {@link Font#getSize}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public float getSize (Font font)
+ {
+ return size;
+ }
+
+ /**
+ * Implementation of {@link Font#isPlain}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public boolean isPlain (Font font)
+ {
+ return style == Font.PLAIN;
+ }
+
+ /**
+ * Implementation of {@link Font#isBold}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public boolean isBold (Font font)
+ {
+ return ((style & Font.BOLD) == Font.BOLD);
+ }
+
+ /**
+ * Implementation of {@link Font#isItalic}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public boolean isItalic (Font font)
+ {
+ return ((style & Font.ITALIC) == Font.ITALIC);
+ }
+
+ /**
+ * Implementation of {@link Font#deriveFont(int, float)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public Font deriveFont (Font font, int style, float size)
+ {
+ Map attrs = new HashMap ();
+ getStandardAttributes (attrs);
+ copyStyleToAttrs (style, attrs);
+ copySizeToAttrs (size, attrs);
+ return tk().getFont (logicalName, attrs);
+ }
+
+ /**
+ * Implementation of {@link Font#deriveFont(float)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public Font deriveFont (Font font, float size)
+ {
+ Map attrs = new HashMap ();
+ getStandardAttributes (attrs);
+ copySizeToAttrs (size, attrs);
+ return tk().getFont (logicalName, attrs);
+ }
+
+ /**
+ * Implementation of {@link Font#deriveFont(int)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public Font deriveFont (Font font, int style)
+ {
+ Map attrs = new HashMap ();
+ getStandardAttributes (attrs);
+ copyStyleToAttrs (style, attrs);
+ return tk().getFont (logicalName, attrs);
+ }
+
+ /**
+ * Implementation of {@link Font#deriveFont(int, AffineTransform)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public Font deriveFont (Font font, int style, AffineTransform t)
+ {
+ Map attrs = new HashMap ();
+ getStandardAttributes (attrs);
+ copyStyleToAttrs (style, attrs);
+ copyTransformToAttrs (t, attrs);
+ return tk().getFont (logicalName, attrs);
+ }
+
+ /**
+ * Implementation of {@link Font#deriveFont(AffineTransform)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public Font deriveFont (Font font, AffineTransform t)
+ {
+ Map attrs = new HashMap ();
+ getStandardAttributes (attrs);
+ copyTransformToAttrs (t, attrs);
+ return tk().getFont (logicalName, attrs);
+ }
+
+ /**
+ * Implementation of {@link Font#deriveFont(Map)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public Font deriveFont (Font font, Map attrs)
+ {
+ return tk().getFont (logicalName, attrs);
+ }
+
+ /**
+ * Implementation of {@link Font#getAttributes()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public Map getAttributes (Font font)
+ {
+ HashMap h = new HashMap ();
+ getStandardAttributes (h);
+ return h;
+ }
+
+ /**
+ * Implementation of {@link Font#getAvailableAttributes()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public AttributedCharacterIterator.Attribute[] getAvailableAttributes(Font font)
+ {
+ AttributedCharacterIterator.Attribute a[] =
+ new AttributedCharacterIterator.Attribute[5];
+ a[0] = TextAttribute.FAMILY;
+ a[1] = TextAttribute.SIZE;
+ a[2] = TextAttribute.POSTURE;
+ a[3] = TextAttribute.WEIGHT;
+ a[4] = TextAttribute.TRANSFORM;
+ return a;
+ }
+
+ /**
+ * Implementation of {@link Font#getTransform()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public AffineTransform getTransform (Font font)
+ {
+ if (transform == null)
+ transform = new AffineTransform ();
+ return transform;
+ }
+
+ /**
+ * Implementation of {@link Font#isTransformed()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public boolean isTransformed (Font font)
+ {
+ return ! transform.isIdentity ();
+ }
+
+ /**
+ * Implementation of {@link Font#getItalicAngle()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public float getItalicAngle (Font font)
+ {
+ if ((style & Font.ITALIC) == Font.ITALIC)
+ return TextAttribute.POSTURE_OBLIQUE.floatValue ();
+ else
+ return TextAttribute.POSTURE_REGULAR.floatValue ();
+ }
+
+
+ /**
+ * Implementation of {@link Font#getStyle()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public int getStyle (Font font)
+ {
+ return style;
+ }
+
+
+
+
+ /* Remaining methods are abstract */
+
+ /**
+ * Implementation of {@link Font#canDisplay(char)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public abstract boolean canDisplay (Font font, int c);
+
+ /**
+ * Implementation of {@link Font#canDisplay(String)},
+ * {@link Font#canDisplay(char [], int, int)}, and
+ * {@link Font#canDisplay(CharacterIterator, int, int)}.
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public abstract int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit);
+
+
+ /**
+ * Returns the name of this font face inside the family, for example
+ * <i>&#x201c;Light&#x201d;</i>.
+ *
+ * <p>This method is currently not used by {@link Font}. However,
+ * this name would be needed by any serious desktop publishing
+ * application.
+ *
+ * @param font the font whose sub-family name is requested.
+ *
+ * @param locale the locale for which to localize the name. If
+ * <code>locale</code> is <code>null</code>, the returned name is
+ * localized to the user&#x2019;s default locale.
+ *
+ * @return the name of the face inside its family, or
+ * <code>null</code> if the font does not provide a sub-family name.
+ */
+
+ public abstract String getSubFamilyName (Font font, Locale locale);
+
+
+ /**
+ * Implementation of {@link Font#getPSName()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public abstract String getPostScriptName (Font font);
+
+
+ /**
+ * Implementation of {@link Font#getNumGlyphs()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public abstract int getNumGlyphs (Font font);
+
+
+ /**
+ * Implementation of {@link Font#getMissingGlyphCode()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public abstract int getMissingGlyphCode (Font font);
+
+
+ /**
+ * Implementation of {@link Font#getBaselineFor(char)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public abstract byte getBaselineFor (Font font, char c);
+
+
+ /**
+ * Returns a name for the specified glyph. This is useful for
+ * generating PostScript or PDF files that embed some glyphs of a
+ * font. If the implementation follows glyph naming conventions
+ * specified by Adobe, search engines can extract the original text
+ * from the generated PostScript and PDF files.
+ *
+ * <p>This method is currently not used by GNU Classpath. However,
+ * it would be very useful for someone wishing to write a good
+ * PostScript or PDF stream provider for the
+ * <code>javax.print</code> package.
+ *
+ * <p><b>Names are not unique:</b> Under some rare circumstances,
+ * the same name can be returned for different glyphs. It is
+ * therefore recommended that printer drivers check whether the same
+ * name has already been returned for antoher glyph, and make the
+ * name unique by adding the string ".alt" followed by the glyph
+ * index.</p>
+ *
+ * <p>This situation would occur for an OpenType or TrueType font
+ * that has a <code>post</code> table of format 3 and provides a
+ * mapping from glyph IDs to Unicode sequences through a
+ * <code>Zapf</code> table. If the same sequence of Unicode
+ * codepoints leads to different glyphs (depending on contextual
+ * position, for example, or on typographic sophistication level),
+ * the same name would get synthesized for those glyphs. To avoid
+ * this, the font peer would have to go through the names of all
+ * glyphs, which would make this operation very inefficient with
+ * large fonts.
+ *
+ * @param font the font containing the glyph whose name is
+ * requested.
+ *
+ * @param glyphIndex the glyph whose name the caller wants to
+ * retrieve.
+ *
+ * @return the glyph name, or <code>null</code> if a font does not
+ * provide glyph names.
+ */
+
+ public abstract String getGlyphName (Font font, int glyphIndex);
+
+
+ /**
+ * Implementation of {@link
+ * Font#createGlyphVector(FontRenderContext, String)}, {@link
+ * Font#createGlyphVector(FontRenderContext, char[])}, and {@link
+ * Font#createGlyphVector(FontRenderContext, CharacterIterator)}.
+ *
+ * @param font the font object that the created GlyphVector will return
+ * when it gets asked for its font. This argument is needed because the
+ * public API of {@link GlyphVector} works with {@link java.awt.Font},
+ * not with font peers.
+ */
+
+ public abstract GlyphVector createGlyphVector (Font font,
+ FontRenderContext frc,
+ CharacterIterator ci);
+
+
+ /**
+ * Implementation of {@link Font#createGlyphVector(FontRenderContext,
+ * int[])}.
+ *
+ * @param font the font object that the created GlyphVector will return
+ * when it gets asked for its font. This argument is needed because the
+ * public API of {@link GlyphVector} works with {@link java.awt.Font},
+ * not with font peers.
+ */
+
+ public abstract GlyphVector createGlyphVector (Font font,
+ FontRenderContext ctx,
+ int[] glyphCodes);
+
+
+ /**
+ * Implementation of {@link Font#layoutGlyphVector(FontRenderContext,
+ * char[], int, int, int)}.
+ *
+ * @param font the font object that the created GlyphVector will return
+ * when it gets asked for its font. This argument is needed because the
+ * public API of {@link GlyphVector} works with {@link java.awt.Font},
+ * not with font peers.
+ */
+
+ public abstract GlyphVector layoutGlyphVector (Font font,
+ FontRenderContext frc,
+ char[] chars, int start,
+ int limit, int flags);
+
+
+ /**
+ * Implementation of {@link Font#getFontMetrics()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public abstract FontMetrics getFontMetrics (Font font);
+
+
+ /**
+ * Implementation of {@link Font#hasUniformLineMetrics()}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public abstract boolean hasUniformLineMetrics (Font font);
+
+
+ /**
+ * Implementation of {@link Font#getLineMetrics(CharacterIterator, int,
+ * int, FontRenderContext)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public abstract LineMetrics getLineMetrics (Font font,
+ CharacterIterator ci,
+ int begin, int limit,
+ FontRenderContext rc);
+
+ /**
+ * Implementation of {@link Font#getMaxCharBounds(FontRenderContext)}
+ *
+ * @param font the font this peer is being called from. This may be
+ * useful if you are sharing peers between Font objects. Otherwise it may
+ * be ignored.
+ */
+
+ public abstract Rectangle2D getMaxCharBounds (Font font,
+ FontRenderContext rc);
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/EmbeddedWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/EmbeddedWindowPeer.java
new file mode 100644
index 000000000..4c64a1d2d
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/EmbeddedWindowPeer.java
@@ -0,0 +1,47 @@
+/* EmbeddedWindowPeer.java -- Interface for window peers that may be
+ embedded into other applications
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer;
+
+import java.awt.peer.FramePeer;
+
+public interface EmbeddedWindowPeer extends FramePeer
+{
+ void embed (long handle);
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java b/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java
new file mode 100644
index 000000000..fe128c26c
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java
@@ -0,0 +1,461 @@
+/* GLightweightPeer.java --
+ Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer;
+
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.BufferCapabilities;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+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;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.VolatileImage;
+import java.awt.peer.ContainerPeer;
+import java.awt.peer.LightweightPeer;
+
+/**
+ * A stub class that implements the ComponentPeer and ContainerPeer
+ * interfaces using callbacks into the Component and Container
+ * classes. GLightweightPeer allows the Component and Container
+ * classes to treat lightweight and heavyweight peers in the same way.
+ *
+ * Lightweight components are painted directly onto their parent
+ * containers through an Image object provided by the toolkit.
+ */
+public class GLightweightPeer
+ implements LightweightPeer, ContainerPeer
+{
+ public GLightweightPeer()
+ {
+ // Nothing to do here.
+ }
+
+ // -------- java.awt.peer.ContainerPeer implementation:
+
+ public Insets insets()
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public Insets getInsets()
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public void beginValidate()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void endValidate()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void beginLayout()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void endLayout()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public boolean isPaintPending()
+ {
+ // Nothing to do here for lightweights.
+ return false;
+ }
+
+ // -------- java.awt.peer.ComponentPeer implementation:
+
+ public int checkImage(Image img, int width, int height, ImageObserver o)
+ {
+ // Nothing to do here for lightweights.
+ return -1;
+ }
+
+ public Image createImage(ImageProducer prod)
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ /* This method is not called. */
+ public Image createImage(int width, int height)
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public void disable()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void dispose()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void enable()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public GraphicsConfiguration getGraphicsConfiguration()
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public FontMetrics getFontMetrics(Font f)
+ {
+ // We shouldn't end up here, but if we do we can still try do something
+ // reasonable.
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ return tk.getFontMetrics(f);
+ }
+
+ /* Returning null here tells the Component object that called us to
+ * use its parent's Graphics. */
+ public Graphics getGraphics()
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public Point getLocationOnScreen()
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public Dimension getMinimumSize()
+ {
+ return minimumSize();
+ }
+
+ public Dimension getPreferredSize()
+ {
+ return preferredSize();
+ }
+
+ /* Returning null here tells the Component object that called us to
+ * use its parent's Toolkit. */
+ public Toolkit getToolkit()
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public void handleEvent(AWTEvent e)
+ {
+ // This can only happen when an application posts a PaintEvent for
+ // a lightweight component directly. We still support painting for
+ // this case.
+ if (e instanceof PaintEvent)
+ {
+ PaintEvent pe = (PaintEvent) e;
+ Component target = (Component) e.getSource();
+ if (target != null && target.isShowing())
+ {
+ Graphics g = target.getGraphics();
+ if (g != null)
+ {
+ try
+ {
+ Rectangle clip = pe.getUpdateRect();
+ g.setClip(clip);
+ target.paint(g);
+ }
+ finally
+ {
+ g.dispose();
+ }
+ }
+ }
+ }
+ }
+
+ public void hide()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public boolean isFocusable()
+ {
+ // Nothing to do here for lightweights.
+ return false;
+ }
+
+ public boolean isFocusTraversable()
+ {
+ // Nothing to do here for lightweights.
+ return false;
+ }
+
+ public Dimension minimumSize()
+ {
+ return new Dimension(0, 0);
+ }
+
+ public Dimension preferredSize()
+ {
+ return new Dimension(0, 0);
+ }
+
+ public void paint(Graphics graphics)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public boolean prepareImage(Image img, int width, int height,
+ ImageObserver o)
+ {
+ // Nothing to do here for lightweights.
+ return false;
+ }
+
+ public void print(Graphics graphics)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void repaint(long tm, int x, int y, int width, int height)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void requestFocus()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public boolean requestFocus(Component source, boolean bool1, boolean bool2,
+ long x)
+ {
+ // Nothing to do here for lightweights.
+ return false;
+ }
+
+ public void reshape(int x, int y, int width, int height)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void setBackground(Color color)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void setBounds(int x, int y, int width, int height)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ /**
+ * Sets the cursor on the heavy-weight parent peer.
+ * Called by the MouseListener on mouse enter.
+ */
+ public void setCursor(Cursor cursor)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void setEnabled(boolean enabled)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void setEventMask(long eventMask)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void setFont(Font font)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void setForeground(Color color)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void setVisible(boolean visible)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void show()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public ColorModel getColorModel()
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public boolean isObscured()
+ {
+ // Nothing to do here for lightweights.
+ return false;
+ }
+
+ public boolean canDetermineObscurity()
+ {
+ // Nothing to do here for lightweights.
+ return false;
+ }
+
+ public void coalescePaintEvent(PaintEvent e)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void updateCursorImmediately()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public VolatileImage createVolatileImage(int width, int height)
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public boolean handlesWheelScrolling()
+ {
+ // Nothing to do here for lightweights.
+ return false;
+ }
+
+ public void createBuffers(int x, BufferCapabilities capabilities)
+ throws AWTException
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public Image getBackBuffer()
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public void flip(BufferCapabilities.FlipContents contents)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void destroyBuffers()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public boolean isRestackSupported()
+ {
+ // Nothing to do here for lightweights.
+ return false;
+ }
+
+ public void cancelPendingPaint(int x, int y, int width, int height)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void restack()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public Rectangle getBounds()
+ {
+ // Nothing to do here for lightweights.
+ return null;
+ }
+
+ public void reparent(ContainerPeer parent)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public void setBounds(int x, int y, int z, int width, int height)
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public boolean isReparentSupported()
+ {
+ // Nothing to do here for lightweights.
+ return true;
+ }
+
+ public void layout()
+ {
+ // Nothing to do here for lightweights.
+ }
+
+ public boolean requestFocus(Component lightweightChild, boolean temporary,
+ boolean focusedWindowChangeAllowed,
+ long time, sun.awt.CausedFocusEvent.Cause cause)
+ {
+ // Always grant focus request.
+ return true;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java b/libjava/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java
new file mode 100644
index 000000000..2347371ad
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/GnomeDesktopPeer.java
@@ -0,0 +1,155 @@
+/* GnomeDesktopPeer.java -- Offers a GNOME Desktop peer for DesktopPeer
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+package gnu.java.awt.peer;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+
+/**
+ * @author Mario Torre <neugens@limasoftware.net>
+ */
+public class GnomeDesktopPeer
+ extends ClasspathDesktopPeer
+{
+ /**
+ * Query string to use if a GNOME desktop is detected to get the name of the
+ * default browser. This requires gconftool-2 (part of GNOME).
+ */
+ private static final String BROWSER_QUERY_GNOME =
+ "gconftool-2 -g /desktop/gnome/url-handlers/http/command";
+
+ protected String getCommand(String action)
+ {
+ // check if a command already exists
+ String command = super.getCommand(action);
+
+ if (command == null)
+ {
+ try
+ {
+ if (action == _BROWSE)
+ {
+ command = execQuery(BROWSER_QUERY_GNOME);
+ }
+ else if (action == _PRINT)
+ {
+ command = null;
+ }
+ else
+ {
+ command = "gnome-open";
+ }
+ }
+ catch (Exception e)
+ {
+ command = null;
+ }
+ }
+
+ return command;
+ }
+
+ public void browse(URI url) throws IOException
+ {
+ checkPermissions();
+
+ String browser = getCommand(_BROWSE);
+
+ if (browser == null)
+ throw new UnsupportedOperationException();
+
+ browser = browser + " " + url.toString();
+
+ Runtime.getRuntime().exec(browser);
+ }
+
+ protected boolean supportCommand(String check)
+ {
+ if (check == _PRINT)
+ {
+ return super.supportCommand(check);
+ }
+
+ return true;
+ }
+
+ public void mail() throws IOException
+ {
+ checkPermissions();
+
+ String mail = getCommand(_MAIL);
+
+ if (mail == null)
+ throw new UnsupportedOperationException();
+
+ Runtime.getRuntime().exec(mail + " mailto:");
+ }
+
+ protected String execQuery(String command) throws IOException
+ {
+ InputStream in = null;
+ CPStringBuilder output = new CPStringBuilder();
+
+ try
+ {
+ Process process = Runtime.getRuntime().exec(command);
+
+ // Get the input stream and read from it
+ in = process.getInputStream();
+ int c;
+ while ((c = in.read()) != - 1)
+ {
+ output.append((char) c);
+ }
+ }
+ finally
+ {
+ if (in != null)
+ in.close();
+ }
+
+ // remove %s from the string, leave only the command line
+ int index = output.indexOf("%s");
+ output.delete(index, index + 1);
+
+ return output.toString().trim();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/KDEDesktopPeer.java b/libjava/classpath/gnu/java/awt/peer/KDEDesktopPeer.java
new file mode 100644
index 000000000..44a508435
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/KDEDesktopPeer.java
@@ -0,0 +1,135 @@
+/* GnomeDesktopPeer.java -- Offers a KDE Desktop peer for DesktopPeer
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+package gnu.java.awt.peer;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author Mario Torre <neugens@limasoftware.net>
+ */
+public class KDEDesktopPeer
+ extends ClasspathDesktopPeer
+{
+ /**
+ * Query string to use if a GNOME desktop is detected to get the name of the
+ * default browser. This requires gconftool-2 (part of GNOME).
+ */
+ private static final String BROWSER_QUERY_GNOME =
+ "gconftool-2 -g /desktop/gnome/url-handlers/http/command";
+
+ protected String getCommand(String action)
+ {
+ // check if a command already exists
+ String command = super.getCommand(action);
+
+ if (command == null)
+ {
+ try
+ {
+ if (action == _MAIL)
+ {
+ command = "kfmclient exec";
+ }
+ else if (action == _PRINT)
+ {
+ command = "kprinter";
+ }
+ else
+ {
+ command = "kfmclient openURL";
+ }
+ }
+ catch (Exception e)
+ {
+ command = null;
+ }
+ }
+
+ return command;
+ }
+
+ protected boolean supportCommand(String check)
+ {
+ return true;
+ }
+
+ public void mail() throws IOException
+ {
+ checkPermissions();
+
+ String mail = getCommand(_MAIL);
+
+ if (mail == null)
+ throw new UnsupportedOperationException();
+
+ Runtime.getRuntime().exec(mail + " 'mailto: '");
+ }
+
+ protected String execQuery(String command) throws IOException
+ {
+ InputStream in = null;
+ CPStringBuilder output = new CPStringBuilder();
+
+ try
+ {
+ Process process = Runtime.getRuntime().exec(command);
+
+ // Get the input stream and read from it
+ in = process.getInputStream();
+ int c;
+ while ((c = in.read()) != - 1)
+ {
+ output.append((char) c);
+ }
+ }
+ finally
+ {
+ if (in != null)
+ in.close();
+ }
+
+ // remove %s from the string, leave only the command line
+ int index = output.indexOf("%s");
+ output.delete(index, index + 1);
+
+ return output.toString().trim();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/NativeEventLoopRunningEvent.java b/libjava/classpath/gnu/java/awt/peer/NativeEventLoopRunningEvent.java
new file mode 100644
index 000000000..962ecd990
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/NativeEventLoopRunningEvent.java
@@ -0,0 +1,58 @@
+/* NativeEventLoopRunningEvent.java -- communicates to EventQueue the
+ state of the native event loop
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer;
+
+import java.awt.AWTEvent;
+
+public class NativeEventLoopRunningEvent
+ extends AWTEvent
+{
+ private boolean running;
+
+ public NativeEventLoopRunningEvent(Object source)
+ {
+ super(source, 2999);
+ running = ((Boolean) source).booleanValue();
+ }
+
+ public boolean isRunning()
+ {
+ return running;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/AsyncImage.java b/libjava/classpath/gnu/java/awt/peer/gtk/AsyncImage.java
new file mode 100644
index 000000000..786dcf26b
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/AsyncImage.java
@@ -0,0 +1,283 @@
+/* AsyncImage.java -- Loads images asynchronously
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * Supports asynchronous loading of images.
+ */
+public class AsyncImage
+ extends Image
+{
+
+ /**
+ * Returned as source as long as the image is not complete.
+ */
+ private class NullImageSource
+ implements ImageProducer
+ {
+ private ArrayList<ImageConsumer> consumers;
+
+ NullImageSource()
+ {
+ consumers = new ArrayList<ImageConsumer>();
+ }
+
+ public void addConsumer(ImageConsumer ic)
+ {
+ consumers.add(ic);
+ }
+
+ public boolean isConsumer(ImageConsumer ic)
+ {
+ return consumers.contains(ic);
+ }
+
+ public void removeConsumer(ImageConsumer ic)
+ {
+ consumers.remove(ic);
+ }
+
+ public void requestTopDownLeftRightResend(ImageConsumer ic)
+ {
+ startProduction(ic);
+ }
+
+ public void startProduction(ImageConsumer ic)
+ {
+ consumers.add(ic);
+ for (int i = consumers.size() - 1; i >= 0; i--)
+ {
+ ImageConsumer c = (ImageConsumer) consumers.get(i);
+ c.setDimensions(1, 1);
+ ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
+ }
+ }
+
+ }
+
+ /**
+ * Loads the image asynchronously.
+ */
+ private class Loader
+ implements Runnable
+ {
+ private URL url;
+ Loader(URL u)
+ {
+ url = u;
+ }
+
+ public void run()
+ {
+ Image image;
+ try
+ {
+ GtkImage gtkImage = new GtkImage(url);
+ image = CairoSurface.getBufferedImage(gtkImage);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ image = null;
+ }
+ realImage = GtkToolkit.imageOrError(image);
+ synchronized (AsyncImage.this)
+ {
+ notifyObservers(ImageObserver.ALLBITS | ImageObserver.HEIGHT
+ | ImageObserver.WIDTH | ImageObserver.PROPERTIES);
+ observers = null; // Not needed anymore.
+ }
+ }
+ }
+
+ /**
+ * The real image. This is null as long as the image is not complete.
+ */
+ Image realImage;
+
+ /**
+ * The image observers.
+ *
+ * This is package private to avoid accessor methods.
+ */
+ HashSet<ImageObserver> observers;
+
+ /**
+ * Creates a new AsyncImage that loads from the specified URL.
+ */
+ AsyncImage(URL url)
+ {
+ observers = new HashSet<ImageObserver>();
+ Loader l = new Loader(url);
+ Thread t = new Thread(l);
+ t.start();
+ }
+
+ public void flush()
+ {
+ // Nothing to do here.
+ }
+
+ public Graphics getGraphics()
+ {
+ Image r = realImage;
+ Graphics g = null;
+ if (r != null)
+ g = r.getGraphics(); // Should we return some dummy graphics instead?
+ return g;
+ }
+
+ public int getHeight(ImageObserver observer)
+ {
+ addObserver(observer);
+ int height = 0;
+ Image r = realImage;
+ if (r != null)
+ height = r.getHeight(observer);
+ return height;
+ }
+
+ public Object getProperty(String name, ImageObserver observer)
+ {
+ addObserver(observer);
+ Image r = realImage;
+ Object prop = null;
+ if (r != null)
+ prop = r.getProperty(name, observer);
+ return prop;
+ }
+
+ public ImageProducer getSource()
+ {
+ Image r = realImage;
+ ImageProducer source;
+ if (r == null)
+ source = new NullImageSource();
+ else
+ source = r.getSource();
+ return source;
+ }
+
+ public int getWidth(ImageObserver observer)
+ {
+ addObserver(observer);
+ int width = 0;
+ Image r = realImage;
+ if (r != null)
+ width = r.getWidth(observer);
+ return width;
+ }
+
+ void addObserver(ImageObserver obs)
+ {
+ if (obs != null)
+ {
+ synchronized (this)
+ {
+ // This field gets null when image loading is complete and we don't
+ // need to store any more observers.
+ HashSet<ImageObserver> observs = observers;
+ if (observs != null)
+ {
+ observs.add(obs);
+ }
+ else
+ {
+ // When the image is complete, notify the observer. Dunno if
+ // that's really needed, but to be sure.
+ obs.imageUpdate(this, ImageObserver.WIDTH
+ | ImageObserver.HEIGHT
+ |ImageObserver.ALLBITS
+ | ImageObserver.PROPERTIES, 0, 0,
+ realImage.getWidth(null),
+ realImage.getHeight(null));
+ }
+ }
+ }
+ }
+
+ static Image realImage(Image img, ImageObserver obs)
+ {
+ if (img instanceof AsyncImage)
+ {
+ ((AsyncImage) img).addObserver(obs);
+ Image r = ((AsyncImage) img).realImage;
+ if (r != null)
+ img = r;
+ }
+ return img;
+ }
+
+ void notifyObservers(int status)
+ {
+ assert Thread.holdsLock(this);
+ // This field gets null when image loading is complete.
+ HashSet observs = observers;
+ if (observs != null)
+ {
+ Image r = realImage;
+ Iterator i = observs.iterator();
+ while (i.hasNext())
+ {
+ ImageObserver obs = (ImageObserver) i.next();
+ obs.imageUpdate(this, status, 0, 0, r.getWidth(null),
+ r.getHeight(null));
+ }
+ }
+ }
+
+ int checkImage(ImageObserver obs)
+ {
+ addObserver(obs);
+ int flags = 0;
+ if (realImage != null)
+ flags = ImageObserver.ALLBITS | ImageObserver.WIDTH
+ | ImageObserver.HEIGHT | ImageObserver.PROPERTIES;
+ return flags;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
new file mode 100644
index 000000000..f9609bff6
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
@@ -0,0 +1,538 @@
+/* BufferedImageGraphics.java
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Toolkit;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBufferInt;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.util.WeakHashMap;
+
+/**
+ * Implementation of Graphics2D on a Cairo surface.
+ *
+ * Simutanously maintains a CairoSurface and updates the
+ * BufferedImage from that after each drawing operation.
+ */
+public class BufferedImageGraphics extends CairoGraphics2D
+{
+ /**
+ * the buffered Image.
+ */
+ private BufferedImage image, buffer;
+
+ /**
+ * Image size.
+ */
+ private int imageWidth, imageHeight;
+
+ /**
+ * The cairo surface that we actually draw on.
+ */
+ CairoSurface surface;
+
+ /**
+ * Cache BufferedImageGraphics surfaces.
+ */
+ static WeakHashMap<BufferedImage, CairoSurface> bufferedImages
+ = new WeakHashMap<BufferedImage, CairoSurface>();
+
+ /**
+ * Its corresponding cairo_t.
+ */
+ private long cairo_t;
+
+ private boolean hasFastCM;
+ private boolean hasAlpha;
+
+
+ public BufferedImageGraphics(BufferedImage bi)
+ {
+ this.image = bi;
+ imageWidth = bi.getWidth();
+ imageHeight = bi.getHeight();
+
+ if (!(image.getSampleModel() instanceof SinglePixelPackedSampleModel))
+ hasFastCM = false;
+ else if(bi.getColorModel().equals(CairoSurface.cairoCM_opaque))
+ {
+ hasFastCM = true;
+ hasAlpha = false;
+ }
+ else if(bi.getColorModel().equals(CairoSurface.cairoColorModel)
+ || bi.getColorModel().equals(CairoSurface.cairoCM_pre))
+ {
+ hasFastCM = true;
+ hasAlpha = true;
+ }
+ else
+ hasFastCM = false;
+
+ // Cache surfaces.
+ if( bufferedImages.get( bi ) != null )
+ surface = bufferedImages.get( bi );
+ else
+ {
+ surface = new CairoSurface( imageWidth, imageHeight );
+ bufferedImages.put(bi, surface);
+ }
+
+ cairo_t = surface.newCairoContext();
+
+ // Get pixels out of buffered image and set in cairo surface
+ Raster raster = bi.getRaster();
+ int[] pixels;
+
+ if (hasFastCM)
+ {
+ SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel)image.getSampleModel();
+ int minX = image.getRaster().getSampleModelTranslateX();
+ int minY = image.getRaster().getSampleModelTranslateY();
+
+ // Pull pixels directly out of data buffer
+ pixels = ((DataBufferInt)raster.getDataBuffer()).getData();
+
+ // Discard pixels that fall outside of the image's bounds
+ // (ie, this image is actually a subimage of a different image)
+ if (!(sm.getScanlineStride() == imageWidth && minX == 0 && minY == 0))
+ {
+ int[] pixels2 = new int[imageWidth * imageHeight];
+ int scanline = sm.getScanlineStride();
+
+ for (int i = 0; i < imageHeight; i++)
+ System.arraycopy(pixels, (i - minY) * scanline - minX, pixels2,
+ i * imageWidth, imageWidth);
+
+ pixels = pixels2;
+ }
+
+ // Fill the alpha channel as opaque if image does not have alpha
+ if( !hasAlpha )
+ for(int i = 0; i < pixels.length; i++)
+ pixels[i] &= 0xFFFFFFFF;
+ }
+ else
+ {
+ pixels = CairoGraphics2D.findSimpleIntegerArray(image.getColorModel(),
+ image.getData());
+ if (pixels != null)
+ System.arraycopy(pixels, 0, surface.getData(),
+ 0, pixels.length);
+ }
+
+ setup( cairo_t );
+ setClip(0, 0, imageWidth, imageHeight);
+ }
+
+ BufferedImageGraphics(BufferedImageGraphics copyFrom)
+ {
+ image = copyFrom.image;
+ surface = copyFrom.surface;
+ cairo_t = surface.newCairoContext();
+ imageWidth = copyFrom.imageWidth;
+ imageHeight = copyFrom.imageHeight;
+
+ hasFastCM = copyFrom.hasFastCM;
+ hasAlpha = copyFrom.hasAlpha;
+
+ copy( copyFrom, cairo_t );
+ }
+
+ /**
+ * Update a rectangle of the bufferedImage. This can be improved upon a lot.
+ */
+ private void updateBufferedImage(int x, int y, int width, int height)
+ {
+ Rectangle bounds = new Rectangle(x, y, width, height);
+ bounds = getTransformedBounds(bounds, transform).getBounds();
+ x = bounds.x;
+ y = bounds.y;
+ width = bounds.width;
+ height = bounds.height;
+
+ int[] pixels = surface.getData();
+
+ if( x > imageWidth || y > imageHeight )
+ return;
+
+ // Deal with negative width/height.
+ if (height < 0)
+ {
+ y += height;
+ height = -height;
+ }
+ if (width < 0)
+ {
+ x += width;
+ width = -width;
+ }
+
+ // Clip edges.
+ if( x < 0 )
+ x = 0;
+ if( y < 0 )
+ y = 0;
+
+ if( x + width > imageWidth )
+ width = imageWidth - x;
+ if( y + height > imageHeight )
+ height = imageHeight - y;
+
+ if(!hasFastCM)
+ {
+ image.setRGB(x, y, width, height, pixels,
+ x + y * imageWidth, imageWidth);
+ // The setRGB method assumes (or should assume) that pixels are NOT
+ // alpha-premultiplied, but Cairo stores data with premultiplication
+ // (thus the pixels returned in getPixels are premultiplied).
+ // This is ignored for consistency, however, since in
+ // CairoGrahpics2D.drawImage we also use non-premultiplied data
+
+ }
+ else
+ {
+ int[] db = ((DataBufferInt)image.getRaster().getDataBuffer()).
+ getData();
+
+ // This should not fail, as we check the image sample model when we
+ // set the hasFastCM flag
+ SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel)image.getSampleModel() ;
+
+ int minX = image.getRaster().getSampleModelTranslateX();
+ int minY = image.getRaster().getSampleModelTranslateY();
+
+ if (sm.getScanlineStride() == imageWidth && minX == 0)
+ {
+ System.arraycopy(pixels, y * imageWidth,
+ db, (y - minY) * imageWidth,
+ height * imageWidth);
+ }
+ else
+ {
+ int scanline = sm.getScanlineStride();
+ for (int i = y; i < (height + y); i++)
+ System.arraycopy(pixels, i * imageWidth + x, db,
+ (i - minY) * scanline + x - minX, width);
+
+ }
+ }
+ }
+
+ /**
+ * Abstract methods.
+ */
+ public Graphics create()
+ {
+ return new BufferedImageGraphics(this);
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ return null;
+ }
+
+ protected Rectangle2D getRealBounds()
+ {
+ return new Rectangle2D.Double(0.0, 0.0, imageWidth, imageHeight);
+ }
+
+ public void copyAreaImpl(int x, int y, int width, int height, int dx, int dy)
+ {
+ surface.copyAreaNative(x, y, width, height, dx, dy, surface.width);
+ updateBufferedImage(x + dx, y + dy, width, height);
+ }
+
+ /**
+ * Overloaded methods that do actual drawing need to enter the gdk threads
+ * and also do certain things before and after.
+ */
+ public void draw(Shape s)
+ {
+ // Find total bounds of shape
+ Rectangle r = findStrokedBounds(s);
+ if (shiftDrawCalls)
+ {
+ r.width++;
+ r.height++;
+ }
+
+ // Do the drawing
+ if (comp == null || comp instanceof AlphaComposite)
+ {
+ super.draw(s);
+ updateBufferedImage(r.x, r.y, r.width, r.height);
+ }
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setStroke(this.getStroke());
+ g2d.setColor(this.getColor());
+ g2d.setTransform(transform);
+ g2d.draw(s);
+
+ drawComposite(r.getBounds2D(), null);
+ }
+ }
+
+ public void fill(Shape s)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ {
+ super.fill(s);
+ Rectangle r = s.getBounds();
+ updateBufferedImage(r.x, r.y, r.width, r.height);
+ }
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setColor(this.getColor());
+ g2d.setTransform(transform);
+ g2d.fill(s);
+
+ drawComposite(s.getBounds2D(), null);
+ }
+ }
+
+ public void drawRenderedImage(RenderedImage image, AffineTransform xform)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ {
+ super.drawRenderedImage(image, xform);
+ updateBufferedImage(0, 0, imageWidth, imageHeight);
+ }
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.setTransform(transform);
+ g2d.drawRenderedImage(image, xform);
+
+ drawComposite(buffer.getRaster().getBounds(), null);
+ }
+
+ }
+
+ protected boolean drawImage(Image img, AffineTransform xform,
+ Color bgcolor, ImageObserver obs)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ {
+ boolean rv = super.drawImage(img, xform, bgcolor, obs);
+ updateBufferedImage(0, 0, imageWidth, imageHeight);
+ return rv;
+ }
+ else
+ {
+ // Get buffered image of source
+ if( !(img instanceof BufferedImage) )
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ img = Toolkit.getDefaultToolkit().createImage(source);
+ }
+ BufferedImage bImg = (BufferedImage) img;
+
+ // Find translated bounds
+ Rectangle2D bounds = new Rectangle(bImg.getMinX(), bImg.getMinY(),
+ bImg.getWidth(), bImg.getHeight());
+ if (xform != null)
+ bounds = getTransformedBounds(bounds, xform);
+
+ // Create buffer and draw image
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.drawImage(img, xform, obs);
+
+ // Perform compositing
+ return drawComposite(bounds, obs);
+ }
+ }
+
+ public void drawGlyphVector(GlyphVector gv, float x, float y)
+ {
+ // Find absolute bounds, in user-space, of this glyph vector
+ Rectangle2D bounds = gv.getLogicalBounds();
+ bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
+ bounds.getWidth(), bounds.getHeight());
+
+ // Perform draw operation
+ if (comp == null || comp instanceof AlphaComposite)
+ {
+ super.drawGlyphVector(gv, x, y);
+
+ // this returns an integer-based Rectangle (rather than a
+ // Rectangle2D), which takes care of any necessary rounding for us.
+ bounds = bounds.getBounds();
+
+ updateBufferedImage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(), (int)bounds.getHeight());
+ }
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setStroke(this.getStroke());
+ g2d.setTransform(transform);
+ g2d.drawGlyphVector(gv, x, y);
+
+ drawComposite(bounds, null);
+ }
+ }
+
+ /**
+ * Perform composite drawing from the buffer onto the main image.
+ *
+ * The image to be composited should already be drawn into the buffer, in the
+ * proper place, after all necessary transforms have been applied.
+ *
+ * @param bounds The bounds to draw, in user-space.
+ * @param observer The image observer, if any (may be null).
+ * @return True on success, false on failure.
+ */
+ private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
+ {
+ // Find bounds in device space
+ bounds = getTransformedBounds(bounds, transform);
+
+ // Clip bounds by the stored clip, and by the internal buffer
+ Rectangle2D devClip = this.getClipInDevSpace();
+ Rectangle2D.intersect(bounds, devClip, bounds);
+ devClip = new Rectangle(buffer.getMinX(), buffer.getMinY(),
+ buffer.getWidth(), buffer.getHeight());
+ Rectangle2D.intersect(bounds, devClip, bounds);
+
+ // Round bounds as needed, but be careful in our rounding
+ // (otherwise it may leave unpainted stripes)
+ double x = bounds.getX();
+ double y = bounds.getY();
+ double maxX = x + bounds.getWidth();
+ double maxY = y + bounds.getHeight();
+ x = Math.round(x);
+ y = Math.round(y);
+ bounds.setRect(x, y, Math.round(maxX - x), Math.round(maxY - y));
+
+ // Find subimage of internal buffer for updating
+ BufferedImage buffer2 = buffer;
+ if (!bounds.equals(buffer2.getRaster().getBounds()))
+ buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(),
+ (int)bounds.getHeight());
+
+ // Find subimage of main image for updating
+ BufferedImage current = image;
+ current = current.getSubimage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(),
+ (int)bounds.getHeight());
+
+ // Perform actual composite operation
+ compCtx.compose(buffer2.getRaster(), current.getRaster(),
+ current.getRaster());
+
+ // Set cairo's composite to direct SRC, since we've already done our own
+ // compositing
+ Composite oldcomp = comp;
+ setComposite(AlphaComposite.Src);
+
+ // This MUST call directly into the "action" method in CairoGraphics2D,
+ // not one of the wrappers, to ensure that the composite isn't processed
+ // more than once!
+ boolean rv = super.drawImage(current,
+ AffineTransform.getTranslateInstance(bounds.getX(),
+ bounds.getY()),
+ null, null);
+ setComposite(oldcomp);
+ updateColor();
+ return rv;
+ }
+
+ private void createBuffer()
+ {
+ if (buffer == null)
+ {
+ buffer = new BufferedImage(image.getWidth(), image.getHeight(),
+ BufferedImage.TYPE_INT_ARGB);
+ }
+ else
+ {
+ Graphics2D g2d = ((Graphics2D)buffer.getGraphics());
+
+ g2d.setBackground(new Color(0,0,0,0));
+ g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
+ }
+ }
+
+ protected ColorModel getNativeCM()
+ {
+ return image.getColorModel();
+ }
+
+ protected ColorModel getBufferCM()
+ {
+ return ColorModel.getRGBdefault();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java
new file mode 100644
index 000000000..05d35c573
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java
@@ -0,0 +1,2176 @@
+/* CairoGraphics2D.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.classpath.Configuration;
+
+import gnu.java.awt.ClasspathToolkit;
+
+import java.awt.AWTPermission;
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.CompositeContext;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.GradientPaint;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.PaintContext;
+import java.awt.Point;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.TexturePaint;
+import java.awt.Toolkit;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.TextLayout;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Arc2D;
+import java.awt.geom.Area;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.ImagingOpException;
+import java.awt.image.MultiPixelPackedSampleModel;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+import java.awt.image.renderable.RenderContext;
+import java.awt.image.renderable.RenderableImage;
+import java.text.AttributedCharacterIterator;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This is an abstract implementation of Graphics2D on Cairo.
+ *
+ * It should be subclassed for different Cairo contexts.
+ *
+ * Note for subclassers: Apart from the constructor (see comments below),
+ * The following abstract methods must be implemented:
+ *
+ * Graphics create()
+ * GraphicsConfiguration getDeviceConfiguration()
+ * copyArea(int x, int y, int width, int height, int dx, int dy)
+ *
+ * Also, dispose() must be overloaded to free any native datastructures
+ * used by subclass and in addition call super.dispose() to free the
+ * native cairographics2d structure and cairo_t.
+ *
+ * @author Sven de Marothy
+ */
+public abstract class CairoGraphics2D extends Graphics2D
+{
+ static
+ {
+ if (true) // GCJ LOCAL
+ {
+ System.loadLibrary("gtkpeer");
+ }
+ }
+
+ /**
+ * Important: This is a pointer to the native cairographics2d structure
+ *
+ * DO NOT CHANGE WITHOUT CHANGING NATIVE CODE.
+ */
+ long nativePointer;
+
+ // Drawing state variables
+ /**
+ * The current paint
+ */
+ Paint paint;
+ boolean customPaint;
+
+ /**
+ * The current stroke
+ */
+ Stroke stroke;
+
+ /*
+ * Current foreground and background color.
+ */
+ Color fg, bg;
+
+ /**
+ * Current clip shape.
+ */
+ Shape clip;
+
+ /**
+ * Current transform.
+ */
+ AffineTransform transform;
+
+ /**
+ * Current font.
+ */
+ Font font;
+
+ /**
+ * The current compositing context, if any.
+ */
+ Composite comp;
+ CompositeContext compCtx;
+
+ /**
+ * Rendering hint map.
+ */
+ private RenderingHints hints;
+
+ /**
+ * Status of the anti-alias flag in cairo.
+ */
+ private boolean antialias = false;
+ private boolean ignoreAA = false;
+
+ /**
+ * Some operations (drawing rather than filling) require that their
+ * coords be shifted to land on 0.5-pixel boundaries, in order to land on
+ * "middle of pixel" coordinates and light up complete pixels.
+ */
+ protected boolean shiftDrawCalls = false;
+
+ /**
+ * Keep track if the first clip to be set, which is restored on setClip(null);
+ */
+ private boolean firstClip = true;
+ private Shape originalClip;
+
+ /**
+ * Stroke used for 3DRects
+ */
+ private static BasicStroke draw3DRectStroke = new BasicStroke();
+
+ static ColorModel rgb32 = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF);
+ static ColorModel argb32 = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF,
+ 0xFF000000);
+
+ /**
+ * Native constants for interpolation methods.
+ * Note, this corresponds to an enum in native/jni/gtk-peer/cairographics2d.h
+ */
+ public static final int INTERPOLATION_NEAREST = 0,
+ INTERPOLATION_BILINEAR = 1,
+ INTERPOLATION_BICUBIC = 5,
+ ALPHA_INTERPOLATION_SPEED = 2,
+ ALPHA_INTERPOLATION_QUALITY = 3,
+ ALPHA_INTERPOLATION_DEFAULT = 4;
+ // TODO: Does ALPHA_INTERPOLATION really correspond to CAIRO_FILTER_FAST/BEST/GOOD?
+
+ /**
+ * Constructor does nothing.
+ */
+ public CairoGraphics2D()
+ {
+ }
+
+ /**
+ * Sets up the default values and allocates the native cairographics2d structure
+ * @param cairo_t_pointer a native pointer to a cairo_t of the context.
+ */
+ public void setup(long cairo_t_pointer)
+ {
+ nativePointer = init(cairo_t_pointer);
+ setRenderingHints(new RenderingHints(getDefaultHints()));
+ setFont(new Font("SansSerif", Font.PLAIN, 12));
+ setColor(Color.black);
+ setBackground(Color.white);
+ setPaint(Color.black);
+ setStroke(new BasicStroke());
+ setTransform(new AffineTransform());
+ cairoSetAntialias(nativePointer, antialias);
+ }
+
+ /**
+ * Same as above, but copies the state of another CairoGraphics2D.
+ */
+ public void copy(CairoGraphics2D g, long cairo_t_pointer)
+ {
+ nativePointer = init(cairo_t_pointer);
+ paint = g.paint;
+ stroke = g.stroke;
+ setRenderingHints(g.hints);
+
+ Color foreground;
+
+ if (g.fg.getAlpha() != -1)
+ foreground = new Color(g.fg.getRed(), g.fg.getGreen(), g.fg.getBlue(),
+ g.fg.getAlpha());
+ else
+ foreground = new Color(g.fg.getRGB());
+
+ if (g.bg != null)
+ {
+ if (g.bg.getAlpha() != -1)
+ bg = new Color(g.bg.getRed(), g.bg.getGreen(), g.bg.getBlue(),
+ g.bg.getAlpha());
+ else
+ bg = new Color(g.bg.getRGB());
+ }
+
+ firstClip = g.firstClip;
+ originalClip = g.originalClip;
+ clip = g.getClip();
+
+ if (g.transform == null)
+ transform = null;
+ else
+ transform = new AffineTransform(g.transform);
+
+ setFont(g.font);
+ setColor(foreground);
+ setBackground(bg);
+ setPaint(paint);
+ setStroke(stroke);
+ setTransformImpl(transform);
+ setClip(clip);
+ setComposite(comp);
+
+ antialias = !g.antialias;
+ setAntialias(g.antialias);
+ }
+
+ /**
+ * Generic destructor - call the native dispose() method.
+ */
+ public void finalize()
+ {
+ dispose();
+ }
+
+ /**
+ * Disposes the native cairographics2d structure, including the
+ * cairo_t and any gradient stuff, if allocated.
+ * Subclasses should of course overload and call this if
+ * they have additional native structures.
+ */
+ public void dispose()
+ {
+ disposeNative(nativePointer);
+ nativePointer = 0;
+ if (compCtx != null)
+ compCtx.dispose();
+ }
+
+ /**
+ * Allocate the cairographics2d structure and set the cairo_t pointer in it.
+ * @param pointer - a cairo_t pointer, casted to a long.
+ */
+ protected native long init(long pointer);
+
+ /**
+ * These are declared abstract as there may be context-specific issues.
+ */
+ public abstract Graphics create();
+
+ public abstract GraphicsConfiguration getDeviceConfiguration();
+
+ protected abstract void copyAreaImpl(int x, int y, int width, int height,
+ int dx, int dy);
+
+
+ /**
+ * Find the bounds of this graphics context, in device space.
+ *
+ * @return the bounds in device-space
+ */
+ protected abstract Rectangle2D getRealBounds();
+
+ ////// Native Methods ////////////////////////////////////////////////////
+
+ /**
+ * Dispose of allocate native resouces.
+ */
+ public native void disposeNative(long pointer);
+
+ /**
+ * Draw pixels as an RGBA int matrix
+ * @param w - width
+ * @param h - height
+ * @param stride - stride of the array width
+ * @param i2u - affine transform array
+ */
+ protected native void drawPixels(long pointer, int[] pixels, int w, int h,
+ int stride, double[] i2u, double alpha,
+ int interpolation);
+
+ protected native void setGradient(long pointer, 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);
+
+ protected native void setPaintPixels(long pointer, int[] pixels, int w,
+ int h, int stride, boolean repeat,
+ int x, int y);
+
+ /**
+ * Set the current transform matrix
+ */
+ protected native void cairoSetMatrix(long pointer, double[] m);
+
+ /**
+ * Scaling method
+ */
+ protected native void cairoScale(long pointer, double x, double y);
+
+ /**
+ * Set the compositing operator
+ */
+ protected native void cairoSetOperator(long pointer, int cairoOperator);
+
+ /**
+ * Sets the current color in RGBA as a 0.0-1.0 double
+ */
+ protected native void cairoSetRGBAColor(long pointer, double red, double green,
+ double blue, double alpha);
+
+ /**
+ * Sets the current winding rule in Cairo
+ */
+ protected native void cairoSetFillRule(long pointer, int cairoFillRule);
+
+ /**
+ * Set the line style, cap, join and miter limit.
+ * Cap and join parameters are in the BasicStroke enumerations.
+ */
+ protected native void cairoSetLine(long pointer, double width, int cap,
+ int join, double miterLimit);
+
+ /**
+ * Set the dash style
+ */
+ protected native void cairoSetDash(long pointer, double[] dashes, int ndash,
+ double offset);
+
+ /*
+ * Draws a Glyph Vector
+ */
+ protected native void cairoDrawGlyphVector(long pointer, GdkFontPeer font,
+ float x, float y, int n,
+ int[] codes, float[] positions, long[] fontset);
+
+ /**
+ * Set the font in cairo.
+ */
+ protected native void cairoSetFont(long pointer, GdkFontPeer font);
+
+ /**
+ * Appends a rectangle to the current path
+ */
+ protected native void cairoRectangle(long pointer, double x, double y,
+ double width, double height);
+
+ /**
+ * Appends an arc to the current path
+ */
+ protected native void cairoArc(long pointer, double x, double y,
+ double radius, double angle1, double angle2);
+
+ /**
+ * Save / restore a cairo path
+ */
+ protected native void cairoSave(long pointer);
+ protected native void cairoRestore(long pointer);
+
+ /**
+ * New current path
+ */
+ protected native void cairoNewPath(long pointer);
+
+ /**
+ * Close current path
+ */
+ protected native void cairoClosePath(long pointer);
+
+ /** moveTo */
+ protected native void cairoMoveTo(long pointer, double x, double y);
+
+ /** lineTo */
+ protected native void cairoLineTo(long pointer, double x, double y);
+
+ /** Cubic curve-to */
+ protected native void cairoCurveTo(long pointer, double x1, double y1,
+ double x2, double y2,
+ double x3, double y3);
+
+ /**
+ * Stroke current path
+ */
+ protected native void cairoStroke(long pointer);
+
+ /**
+ * Fill current path
+ */
+ protected native void cairoFill(long pointer, double alpha);
+
+ /**
+ * Clip current path
+ */
+ protected native void cairoClip(long pointer);
+
+ /**
+ * Clear clip
+ */
+ protected native void cairoResetClip(long pointer);
+
+ /**
+ * Set antialias.
+ */
+ protected native void cairoSetAntialias(long pointer, boolean aa);
+
+
+ ///////////////////////// TRANSFORMS ///////////////////////////////////
+ /**
+ * Set the current transform
+ */
+ public void setTransform(AffineTransform tx)
+ {
+ // Transform clip into target space using the old transform.
+ updateClip(transform);
+
+ // Update the native transform.
+ setTransformImpl(tx);
+
+ // Transform the clip back into user space using the inverse new transform.
+ try
+ {
+ updateClip(transform.createInverse());
+ }
+ catch (NoninvertibleTransformException ex)
+ {
+ // TODO: How can we deal properly with this?
+ ex.printStackTrace();
+ }
+
+ if (clip != null)
+ setClip(clip);
+ }
+
+ private void setTransformImpl(AffineTransform tx)
+ {
+ transform = tx;
+ if (transform != null)
+ {
+ double[] m = new double[6];
+ transform.getMatrix(m);
+ cairoSetMatrix(nativePointer, m);
+ }
+ }
+
+ public void transform(AffineTransform tx)
+ {
+ if (transform == null)
+ transform = new AffineTransform(tx);
+ else
+ transform.concatenate(tx);
+
+ if (clip != null)
+ {
+ try
+ {
+ AffineTransform clipTransform = tx.createInverse();
+ updateClip(clipTransform);
+ }
+ catch (NoninvertibleTransformException ex)
+ {
+ // TODO: How can we deal properly with this?
+ ex.printStackTrace();
+ }
+ }
+
+ setTransformImpl(transform);
+ }
+
+ public void rotate(double theta)
+ {
+ transform(AffineTransform.getRotateInstance(theta));
+ }
+
+ public void rotate(double theta, double x, double y)
+ {
+ transform(AffineTransform.getRotateInstance(theta, x, y));
+ }
+
+ public void scale(double sx, double sy)
+ {
+ transform(AffineTransform.getScaleInstance(sx, sy));
+ }
+
+ /**
+ * Translate the system of the co-ordinates. As translation is a frequent
+ * operation, it is done in an optimised way, unlike scaling and rotating.
+ */
+ public void translate(double tx, double ty)
+ {
+ if (transform != null)
+ transform.translate(tx, ty);
+ else
+ transform = AffineTransform.getTranslateInstance(tx, ty);
+
+ if (clip != null)
+ {
+ // FIXME: this should actuall try to transform the shape
+ // rather than degrade to bounds.
+ if (clip instanceof Rectangle2D)
+ {
+ Rectangle2D r = (Rectangle2D) clip;
+ r.setRect(r.getX() - tx, r.getY() - ty, r.getWidth(),
+ r.getHeight());
+ }
+ else
+ {
+ AffineTransform clipTransform =
+ AffineTransform.getTranslateInstance(-tx, -ty);
+ updateClip(clipTransform);
+ }
+ }
+
+ setTransformImpl(transform);
+ }
+
+ public void translate(int x, int y)
+ {
+ translate((double) x, (double) y);
+ }
+
+ public void shear(double shearX, double shearY)
+ {
+ transform(AffineTransform.getShearInstance(shearX, shearY));
+ }
+
+ ///////////////////////// DRAWING STATE ///////////////////////////////////
+
+ public void clip(Shape s)
+ {
+ // Do not touch clip when s == null.
+ if (s == null)
+ {
+ // The spec says this should clear the clip. The reference
+ // implementation throws a NullPointerException instead. I think,
+ // in this case we should conform to the specs, as it shouldn't
+ // affect compatibility.
+ setClip(null);
+ return;
+ }
+
+ // If the current clip is still null, initialize it.
+ if (clip == null)
+ {
+ clip = getRealBounds();
+ }
+
+ // This is so common, let's optimize this.
+ if (clip instanceof Rectangle2D && s instanceof Rectangle2D)
+ {
+ Rectangle2D clipRect = (Rectangle2D) clip;
+ Rectangle2D r = (Rectangle2D) s;
+ Rectangle2D.intersect(clipRect, r, clipRect);
+ setClip(clipRect);
+ }
+ else
+ {
+ Area current;
+ if (clip instanceof Area)
+ current = (Area) clip;
+ else
+ current = new Area(clip);
+
+ Area intersect;
+ if (s instanceof Area)
+ intersect = (Area) s;
+ else
+ intersect = new Area(s);
+
+ current.intersect(intersect);
+ clip = current;
+ // Call setClip so that the native side gets notified.
+ setClip(clip);
+ }
+ }
+
+ public Paint getPaint()
+ {
+ return paint;
+ }
+
+ public AffineTransform getTransform()
+ {
+ return (AffineTransform) transform.clone();
+ }
+
+ public void setPaint(Paint p)
+ {
+ if (p == null)
+ return;
+
+ paint = p;
+ if (paint instanceof Color)
+ {
+ setColor((Color) paint);
+ customPaint = false;
+ }
+
+ 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 = height / (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);
+ setPaintPixels(nativePointer, pixels, width, height, width, true, 0, 0);
+ customPaint = false;
+ }
+
+ 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();
+ setGradient(nativePointer, 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());
+ customPaint = false;
+ }
+ else
+ {
+ customPaint = true;
+ }
+ }
+
+ /**
+ * Sets a custom paint
+ *
+ * @param bounds the bounding box, in user space
+ */
+ protected void setCustomPaint(Rectangle bounds)
+ {
+ if (paint instanceof Color || paint instanceof TexturePaint
+ || paint instanceof GradientPaint)
+ return;
+
+ int userX = bounds.x;
+ int userY = bounds.y;
+ int userWidth = bounds.width;
+ int userHeight = bounds.height;
+
+ // Find bounds in device space
+ Rectangle2D bounds2D = getTransformedBounds(bounds, transform);
+ int deviceX = (int)bounds2D.getX();
+ int deviceY = (int)bounds2D.getY();
+ int deviceWidth = (int)Math.ceil(bounds2D.getWidth());
+ int deviceHeight = (int)Math.ceil(bounds2D.getHeight());
+
+ // Get raster of the paint background
+ PaintContext pc = paint.createContext(CairoSurface.cairoColorModel,
+ new Rectangle(deviceX, deviceY,
+ deviceWidth,
+ deviceHeight),
+ bounds,
+ transform, hints);
+
+ Raster raster = pc.getRaster(deviceX, deviceY, deviceWidth,
+ deviceHeight);
+
+ // Clear the transform matrix in Cairo, since the raster returned by the
+ // PaintContext is already in device-space
+ AffineTransform oldTx = new AffineTransform(transform);
+ setTransformImpl(new AffineTransform());
+
+ // Set pixels in cairo, aligning the top-left of the background image
+ // to the top-left corner in device space
+ if (pc.getColorModel().equals(CairoSurface.cairoColorModel)
+ && raster.getSampleModel().getTransferType() == DataBuffer.TYPE_INT)
+ {
+ // Use a fast copy if the paint context can uses a Cairo-compatible
+ // color model
+ setPaintPixels(nativePointer,
+ (int[])raster.getDataElements(0, 0, deviceWidth,
+ deviceHeight, null),
+ deviceWidth, deviceHeight, deviceWidth, false,
+ deviceX, deviceY);
+ }
+
+ else if (pc.getColorModel().equals(CairoSurface.cairoCM_opaque)
+ && raster.getSampleModel().getTransferType() == DataBuffer.TYPE_INT)
+ {
+ // We can also optimize if the context uses a similar color model
+ // but without an alpha channel; we just add the alpha
+ int[] pixels = (int[])raster.getDataElements(0, 0, deviceWidth,
+ deviceHeight, null);
+
+ for (int i = 0; i < pixels.length; i++)
+ pixels[i] = 0xff000000 | (pixels[i] & 0x00ffffff);
+
+ setPaintPixels(nativePointer, pixels, deviceWidth, deviceHeight,
+ deviceWidth, false, deviceX, deviceY);
+ }
+
+ else
+ {
+ // Fall back on wrapping the raster in a BufferedImage, and
+ // use BufferedImage.getRGB() to do color-model conversion
+ WritableRaster wr = Raster.createWritableRaster(raster.getSampleModel(),
+ new Point(raster.getMinX(),
+ raster.getMinY()));
+ wr.setRect(raster);
+
+ BufferedImage img2 = new BufferedImage(pc.getColorModel(), wr,
+ pc.getColorModel().isAlphaPremultiplied(),
+ null);
+
+ setPaintPixels(nativePointer,
+ img2.getRGB(0, 0, deviceWidth, deviceHeight, null, 0,
+ deviceWidth),
+ deviceWidth, deviceHeight, deviceWidth, false,
+ deviceX, deviceY);
+ }
+
+ // Restore transform
+ setTransformImpl(oldTx);
+ }
+
+ public Stroke getStroke()
+ {
+ return stroke;
+ }
+
+ public void setStroke(Stroke st)
+ {
+ stroke = st;
+ if (stroke instanceof BasicStroke)
+ {
+ BasicStroke bs = (BasicStroke) stroke;
+ cairoSetLine(nativePointer, bs.getLineWidth(), bs.getEndCap(),
+ bs.getLineJoin(), 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];
+
+ cairoSetDash(nativePointer, double_dashes, double_dashes.length,
+ (double) bs.getDashPhase());
+ }
+ else
+ cairoSetDash(nativePointer, new double[0], 0, 0.0);
+ }
+ }
+
+ /**
+ * Utility method to find the bounds of a shape, including the stroke width.
+ *
+ * @param s the shape
+ * @return the bounds of the shape, including stroke width
+ */
+ protected Rectangle findStrokedBounds(Shape s)
+ {
+ Rectangle r = s.getBounds();
+
+ if (stroke instanceof BasicStroke)
+ {
+ int strokeWidth = (int)Math.ceil(((BasicStroke)stroke).getLineWidth());
+ r.x -= strokeWidth / 2;
+ r.y -= strokeWidth / 2;
+ r.height += strokeWidth;
+ r.width += strokeWidth;
+ }
+ else
+ {
+ Shape s2 = stroke.createStrokedShape(s);
+ r = s2.getBounds();
+ }
+
+ return r;
+ }
+
+ public void setPaintMode()
+ {
+ setComposite(AlphaComposite.SrcOver);
+ }
+
+ public void setXORMode(Color c)
+ {
+ // FIXME: implement
+ }
+
+ public void setColor(Color c)
+ {
+ if (c == null)
+ c = Color.BLACK;
+
+ fg = c;
+ paint = c;
+ updateColor();
+ }
+
+ /**
+ * Set the current fg value as the cairo color.
+ */
+ void updateColor()
+ {
+ if (fg == null)
+ fg = Color.BLACK;
+
+ cairoSetRGBAColor(nativePointer, fg.getRed() / 255.0,
+ fg.getGreen() / 255.0,fg.getBlue() / 255.0,
+ fg.getAlpha() / 255.0);
+ }
+
+ public Color getColor()
+ {
+ return fg;
+ }
+
+ public void clipRect(int x, int y, int width, int height)
+ {
+ if (clip == null)
+ setClip(new Rectangle(x, y, width, height));
+ else if (clip instanceof Rectangle)
+ {
+ computeIntersection(x, y, width, height, (Rectangle) clip);
+ setClip(clip);
+ }
+ else
+ clip(new Rectangle(x, y, width, height));
+ }
+
+ public Shape getClip()
+ {
+ if (clip == null)
+ return null;
+ else if (clip instanceof Rectangle2D)
+ return clip.getBounds2D(); //getClipInDevSpace();
+ else
+ {
+ GeneralPath p = new GeneralPath();
+ PathIterator pi = clip.getPathIterator(null);
+ p.append(pi, false);
+ return p;
+ }
+ }
+
+ public Rectangle getClipBounds()
+ {
+ if (clip == null)
+ return null;
+ else
+ return clip.getBounds();
+ }
+
+ protected Rectangle2D getClipInDevSpace()
+ {
+ Rectangle2D uclip = clip.getBounds2D();
+ if (transform == null)
+ return uclip;
+ else
+ return getTransformedBounds(clip.getBounds2D(), transform);
+ }
+
+ public void setClip(int x, int y, int width, int height)
+ {
+ if( width < 0 || height < 0 )
+ return;
+
+ setClip(new Rectangle2D.Double(x, y, width, height));
+ }
+
+ public void setClip(Shape s)
+ {
+ // The first time the clip is set, save it as the original clip
+ // to reset to on s == null. We can rely on this being non-null
+ // because the constructor in subclasses is expected to set the
+ // initial clip properly.
+ if( firstClip )
+ {
+ originalClip = s;
+ firstClip = false;
+ }
+
+ clip = s;
+ cairoResetClip(nativePointer);
+
+ if (clip != null)
+ {
+ cairoNewPath(nativePointer);
+ if (clip instanceof Rectangle2D)
+ {
+ Rectangle2D r = (Rectangle2D) clip;
+ cairoRectangle(nativePointer, r.getX(), r.getY(), r.getWidth(),
+ r.getHeight());
+ }
+ else
+ walkPath(clip.getPathIterator(null), false);
+
+ cairoClip(nativePointer);
+ }
+ }
+
+ public void setBackground(Color c)
+ {
+ if (c == null)
+ c = Color.WHITE;
+ bg = c;
+ }
+
+ public Color getBackground()
+ {
+ return bg;
+ }
+
+ /**
+ * Return the current composite.
+ */
+ public Composite getComposite()
+ {
+ if (comp == null)
+ return AlphaComposite.SrcOver;
+ else
+ return comp;
+ }
+
+ /**
+ * Sets the current composite context.
+ */
+ public void setComposite(Composite comp)
+ {
+ if (this.comp == comp)
+ return;
+
+ this.comp = comp;
+ if (compCtx != null)
+ compCtx.dispose();
+ compCtx = null;
+
+ if (comp instanceof AlphaComposite)
+ {
+ AlphaComposite a = (AlphaComposite) comp;
+ cairoSetOperator(nativePointer, a.getRule());
+ }
+
+ else
+ {
+ cairoSetOperator(nativePointer, AlphaComposite.SRC_OVER);
+
+ if (comp != null)
+ {
+ // FIXME: this check is only required "if this Graphics2D
+ // context is drawing to a Component on the display screen".
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new AWTPermission("readDisplayPixels"));
+
+ compCtx = comp.createContext(getBufferCM(), getNativeCM(), hints);
+ }
+ }
+ }
+
+ /**
+ * Returns the Colour Model describing the native, raw image data for this
+ * specific peer.
+ *
+ * @return ColorModel the ColorModel of native data in this peer
+ */
+ protected abstract ColorModel getNativeCM();
+
+ /**
+ * Returns the Color Model describing the buffer that this peer uses
+ * for custom composites.
+ *
+ * @return ColorModel the ColorModel of the composite buffer in this peer.
+ */
+ protected ColorModel getBufferCM()
+ {
+ // This may be overridden by some subclasses
+ return getNativeCM();
+ }
+
+ ///////////////////////// DRAWING PRIMITIVES ///////////////////////////////////
+
+ public void draw(Shape s)
+ {
+ if ((stroke != null && ! (stroke instanceof BasicStroke))
+ || (comp instanceof AlphaComposite && ((AlphaComposite) comp).getAlpha() != 1.0))
+ {
+ // Cairo doesn't support stroking with alpha, so we create the stroked
+ // shape and fill with alpha instead
+ fill(stroke.createStrokedShape(s));
+ return;
+ }
+
+ if (customPaint)
+ {
+ Rectangle r = findStrokedBounds(s);
+ setCustomPaint(r);
+ }
+
+ setAntialias(!hints.get(RenderingHints.KEY_ANTIALIASING)
+ .equals(RenderingHints.VALUE_ANTIALIAS_OFF));
+ createPath(s, true);
+ cairoStroke(nativePointer);
+ }
+
+ public void fill(Shape s)
+ {
+ createPath(s, false);
+
+ if (customPaint)
+ setCustomPaint(s.getBounds());
+
+ setAntialias(!hints.get(RenderingHints.KEY_ANTIALIASING)
+ .equals(RenderingHints.VALUE_ANTIALIAS_OFF));
+ double alpha = 1.0;
+ if (comp instanceof AlphaComposite)
+ alpha = ((AlphaComposite) comp).getAlpha();
+ cairoFill(nativePointer, alpha);
+ }
+
+ private void createPath(Shape s, boolean isDraw)
+ {
+ cairoNewPath(nativePointer);
+
+ // Optimize rectangles, since there is a direct Cairo function
+ if (s instanceof Rectangle2D)
+ {
+ Rectangle2D r = (Rectangle2D) s;
+
+ // Pixels need to be shifted in draw operations to ensure that they
+ // light up entire pixels, but we also need to make sure the rectangle
+ // does not get distorted by this shifting operation
+ double x = shiftX(r.getX(),shiftDrawCalls && isDraw);
+ double y = shiftY(r.getY(), shiftDrawCalls && isDraw);
+ double w = Math.round(r.getWidth());
+ double h = Math.round(r.getHeight());
+ cairoRectangle(nativePointer, x, y, w, h);
+ }
+
+ // Lines are easy too
+ else if (s instanceof Line2D)
+ {
+ Line2D l = (Line2D) s;
+ cairoMoveTo(nativePointer, shiftX(l.getX1(), shiftDrawCalls && isDraw),
+ shiftY(l.getY1(), shiftDrawCalls && isDraw));
+ cairoLineTo(nativePointer, shiftX(l.getX2(), shiftDrawCalls && isDraw),
+ shiftY(l.getY2(), shiftDrawCalls && isDraw));
+ }
+
+ // We can optimize ellipses too; however we don't bother optimizing arcs:
+ // the iterator is fast enough (an ellipse requires 5 steps using the
+ // iterator, while most arcs are only 2-3)
+ else if (s instanceof Ellipse2D)
+ {
+ Ellipse2D e = (Ellipse2D) s;
+
+ double radius = Math.min(e.getHeight(), e.getWidth()) / 2;
+
+ // Cairo only draws circular shapes, but we can use a stretch to make
+ // them into ellipses
+ double xscale = 1, yscale = 1;
+ if (e.getHeight() != e.getWidth())
+ {
+ cairoSave(nativePointer);
+
+ if (e.getHeight() < e.getWidth())
+ xscale = e.getWidth() / (radius * 2);
+ else
+ yscale = e.getHeight() / (radius * 2);
+
+ if (xscale != 1 || yscale != 1)
+ cairoScale(nativePointer, xscale, yscale);
+ }
+
+ cairoArc(nativePointer,
+ shiftX(e.getCenterX() / xscale, shiftDrawCalls && isDraw),
+ shiftY(e.getCenterY() / yscale, shiftDrawCalls && isDraw),
+ radius, 0, Math.PI * 2);
+
+ if (xscale != 1 || yscale != 1)
+ cairoRestore(nativePointer);
+ }
+
+ // All other shapes are broken down and drawn in steps using the
+ // PathIterator
+ else
+ walkPath(s.getPathIterator(null), shiftDrawCalls && isDraw);
+ }
+
+ /**
+ * Note that the rest of the drawing methods go via fill() or draw() for the drawing,
+ * although subclasses may with to overload these methods where context-specific
+ * optimizations are possible (e.g. bitmaps and fillRect(int, int, int, int)
+ */
+
+ public void clearRect(int x, int y, int width, int height)
+ {
+ if (bg != null)
+ cairoSetRGBAColor(nativePointer, bg.getRed() / 255.0,
+ bg.getGreen() / 255.0, bg.getBlue() / 255.0,
+ bg.getAlpha() / 255.0);
+
+ Composite oldcomp = comp;
+ setComposite(AlphaComposite.Src);
+ fillRect(x, y, width, height);
+
+ setComposite(oldcomp);
+ updateColor();
+ }
+
+ public void draw3DRect(int x, int y, int width, int height, boolean raised)
+ {
+ Stroke tmp = stroke;
+ setStroke(draw3DRectStroke);
+ super.draw3DRect(x, y, width, height, raised);
+ setStroke(tmp);
+ }
+
+ public void drawArc(int x, int y, int width, int height, int startAngle,
+ int arcAngle)
+ {
+ draw(new Arc2D.Double((double) x, (double) y, (double) width,
+ (double) height, (double) startAngle,
+ (double) arcAngle, Arc2D.OPEN));
+ }
+
+ public void drawLine(int x1, int y1, int x2, int y2)
+ {
+ // The coordinates being pairwise identical means one wants
+ // to draw a single pixel. This is emulated by drawing
+ // a one pixel sized rectangle.
+ if (x1 == x2 && y1 == y2)
+ fill(new Rectangle(x1, y1, 1, 1));
+ else
+ draw(new Line2D.Double(x1, y1, x2, y2));
+ }
+
+ public void drawRect(int x, int y, int width, int height)
+ {
+ draw(new Rectangle(x, y, width, height));
+ }
+
+ public void fillArc(int x, int y, int width, int height, int startAngle,
+ int arcAngle)
+ {
+ fill(new Arc2D.Double((double) x, (double) y, (double) width,
+ (double) height, (double) startAngle,
+ (double) arcAngle, Arc2D.PIE));
+ }
+
+ public void fillRect(int x, int y, int width, int height)
+ {
+ fill (new Rectangle(x, y, width, height));
+ }
+
+ public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)
+ {
+ fill(new Polygon(xPoints, yPoints, nPoints));
+ }
+
+ public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
+ {
+ draw(new Polygon(xPoints, yPoints, nPoints));
+ }
+
+ public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
+ {
+ for (int i = 1; i < nPoints; i++)
+ draw(new Line2D.Double(xPoints[i - 1], yPoints[i - 1],
+ xPoints[i], yPoints[i]));
+ }
+
+ public void drawOval(int x, int y, int width, int height)
+ {
+ drawArc(x, y, width, height, 0, 360);
+ }
+
+ public void drawRoundRect(int x, int y, int width, int height, int arcWidth,
+ int arcHeight)
+ {
+ draw(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight));
+ }
+
+ public void fillOval(int x, int y, int width, int height)
+ {
+ fillArc(x, y, width, height, 0, 360);
+ }
+
+ public void fillRoundRect(int x, int y, int width, int height, int arcWidth,
+ int arcHeight)
+ {
+ fill(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight));
+ }
+
+ /**
+ * CopyArea - performs clipping to the native surface as a convenience
+ * (requires getRealBounds). Then calls copyAreaImpl.
+ */
+ public void copyArea(int ox, int oy, int owidth, int oheight,
+ int odx, int ody)
+ {
+ // FIXME: does this handle a rotation transform properly?
+ // (the width/height might not be correct)
+ Point2D pos = transform.transform(new Point2D.Double(ox, oy),
+ (Point2D) null);
+ Point2D dim = transform.transform(new Point2D.Double(ox + owidth,
+ oy + oheight),
+ (Point2D) null);
+ Point2D p2 = transform.transform(new Point2D.Double(ox + odx, oy + ody),
+ (Point2D) null);
+ int x = (int)pos.getX();
+ int y = (int)pos.getY();
+ int width = (int)(dim.getX() - pos.getX());
+ int height = (int)(dim.getY() - pos.getY());
+ int dx = (int)(p2.getX() - pos.getX());
+ int dy = (int)(p2.getY() - pos.getY());
+
+ Rectangle2D r = getRealBounds();
+
+ if( width <= 0 || height <= 0 )
+ return;
+ // Return if outside the surface
+ if( x + dx > r.getWidth() || y + dy > r.getHeight() )
+ return;
+
+ if( x + dx + width < r.getX() || y + dy + height < r.getY() )
+ return;
+
+ // Clip edges if necessary
+ if( x + dx < r.getX() ) // left
+ {
+ width = x + dx + width;
+ x = (int)r.getX() - dx;
+ }
+
+ if( y + dy < r.getY() ) // top
+ {
+ height = y + dy + height;
+ y = (int)r.getY() - dy;
+ }
+
+ if( x + dx + width >= r.getWidth() ) // right
+ width = (int)r.getWidth() - dx - x;
+
+ if( y + dy + height >= r.getHeight() ) // bottom
+ height = (int)r.getHeight() - dy - y;
+
+ copyAreaImpl(x, y, width, height, dx, dy);
+ }
+
+ ///////////////////////// RENDERING HINTS ///////////////////////////////////
+
+ public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue)
+ {
+ hints.put(hintKey, hintValue);
+
+ shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE)
+ || hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT);
+ }
+
+ public Object getRenderingHint(RenderingHints.Key hintKey)
+ {
+ return hints.get(hintKey);
+ }
+
+ public void setRenderingHints(Map<?,?> hints)
+ {
+ this.hints = new RenderingHints(getDefaultHints());
+ this.hints.putAll(hints);
+
+ shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE)
+ || hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT);
+
+ if (compCtx != null)
+ {
+ compCtx.dispose();
+ compCtx = comp.createContext(getNativeCM(), getNativeCM(), this.hints);
+ }
+ }
+
+ public void addRenderingHints(Map hints)
+ {
+ this.hints.putAll(hints);
+ }
+
+ public RenderingHints getRenderingHints()
+ {
+ return hints;
+ }
+
+ private int getInterpolation()
+ {
+ if (this.hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR))
+ return INTERPOLATION_NEAREST;
+
+ else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR))
+ return INTERPOLATION_BILINEAR;
+
+ else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BICUBIC))
+ return INTERPOLATION_BICUBIC;
+
+ else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED))
+ return ALPHA_INTERPOLATION_SPEED;
+
+ else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY))
+ return ALPHA_INTERPOLATION_QUALITY;
+
+ else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT))
+ return ALPHA_INTERPOLATION_DEFAULT;
+
+ // Do bilinear interpolation as default
+ return INTERPOLATION_BILINEAR;
+ }
+
+ /**
+ * Set antialias if needed. If the ignoreAA flag is set, this method will
+ * return without doing anything.
+ *
+ * @param needAA RenderingHints.VALUE_ANTIALIAS_ON or RenderingHints.VALUE_ANTIALIAS_OFF
+ */
+ private void setAntialias(boolean needAA)
+ {
+ if (ignoreAA)
+ return;
+
+ if (needAA != antialias)
+ {
+ antialias = !antialias;
+ cairoSetAntialias(nativePointer, antialias);
+ }
+ }
+
+ ///////////////////////// IMAGE. METHODS ///////////////////////////////////
+
+ protected boolean drawImage(Image img, AffineTransform xform,
+ Color bgcolor, ImageObserver obs)
+ {
+ if (img == null)
+ return false;
+
+ if (xform == null)
+ xform = new AffineTransform();
+
+ // In this case, xform is an AffineTransform that transforms bounding
+ // box of the specified image from image space to user space. However
+ // when we pass this transform to cairo, cairo will use this transform
+ // to map "user coordinates" to "pixel" coordinates, which is the
+ // other way around. Therefore to get the "user -> pixel" transform
+ // that cairo wants from "image -> user" transform that we currently
+ // have, we will need to invert the transformation matrix.
+ AffineTransform invertedXform;
+
+ try
+ {
+ invertedXform = xform.createInverse();
+ }
+ catch (NoninvertibleTransformException e)
+ {
+ throw new ImagingOpException("Unable to invert transform "
+ + xform.toString());
+ }
+
+ // Unrecognized image - convert to a BufferedImage
+ // Note - this can get us in trouble when the gdk lock is re-acquired.
+ // for example by VolatileImage. See ComponentGraphics for how we work
+ // around this.
+ img = AsyncImage.realImage(img, obs);
+ if( !(img instanceof BufferedImage) )
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ img = Toolkit.getDefaultToolkit().createImage(source);
+ }
+
+ BufferedImage b = (BufferedImage) img;
+ Raster raster;
+ double[] i2u = new double[6];
+ int width = b.getWidth();
+ int height = b.getHeight();
+
+ // If this BufferedImage has a BufferedImageGraphics object,
+ // use the cached CairoSurface that BIG is drawing onto
+
+ if( BufferedImageGraphics.bufferedImages.get( b ) != null )
+ raster = BufferedImageGraphics.bufferedImages.get( b );
+ else
+ raster = b.getRaster();
+
+ invertedXform.getMatrix(i2u);
+
+ double alpha = 1.0;
+ if (comp instanceof AlphaComposite)
+ alpha = ((AlphaComposite) comp).getAlpha();
+
+ if(raster instanceof CairoSurface
+ && ((CairoSurface)raster).sharedBuffer == true)
+ {
+ drawCairoSurface((CairoSurface)raster, xform, alpha, getInterpolation());
+ updateColor();
+ return true;
+ }
+
+ if( bgcolor != null )
+ {
+ Color oldColor = bg;
+ setBackground(bgcolor);
+
+ Rectangle2D bounds = new Rectangle2D.Double(0, 0, width, height);
+ bounds = getTransformedBounds(bounds, xform);
+
+ clearRect((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(), (int)bounds.getHeight());
+
+ setBackground(oldColor);
+ }
+
+ int[] pixels = b.getRGB(0, 0, width, height, null, 0, width);
+ // FIXME: The above method returns data in the standard ARGB colorspace,
+ // meaning data should NOT be alpha pre-multiplied; however Cairo expects
+ // data to be premultiplied.
+
+ cairoSave(nativePointer);
+ Rectangle2D bounds = new Rectangle2D.Double(0, 0, width, height);
+ bounds = getTransformedBounds(bounds, xform);
+ cairoRectangle(nativePointer, bounds.getX(), bounds.getY(),
+ bounds.getWidth(), bounds.getHeight());
+ cairoClip(nativePointer);
+
+ drawPixels(nativePointer, pixels, width, height, width, i2u, alpha,
+ getInterpolation());
+
+ cairoRestore(nativePointer);
+
+ // Cairo seems to lose the current color which must be restored.
+ updateColor();
+ return true;
+ }
+
+ public void drawRenderedImage(RenderedImage image, AffineTransform xform)
+ {
+ drawRaster(image.getColorModel(), image.getData(), xform, null);
+ }
+
+ public void drawRenderableImage(RenderableImage image, AffineTransform xform)
+ {
+ drawRenderedImage(image.createRendering(new RenderContext(xform)), xform);
+ }
+
+ public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs)
+ {
+ return drawImage(img, xform, null, obs);
+ }
+
+ public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y)
+ {
+ Image filtered = image;
+ if (op != null)
+ filtered = op.filter(image, null);
+ drawImage(filtered, new AffineTransform(1f, 0f, 0f, 1f, x, y), null, null);
+ }
+
+ public boolean drawImage(Image img, int x, int y, ImageObserver observer)
+ {
+ return drawImage(img, new AffineTransform(1f, 0f, 0f, 1f, x, y), null,
+ observer);
+ }
+
+ public boolean drawImage(Image img, int x, int y, Color bgcolor,
+ ImageObserver observer)
+ {
+ return drawImage(img, x, y, img.getWidth(observer),
+ img.getHeight(observer), bgcolor, observer);
+ }
+
+ public boolean drawImage(Image img, int x, int y, int width, int height,
+ Color bgcolor, ImageObserver observer)
+ {
+ double scaleX = width / (double) img.getWidth(observer);
+ double scaleY = height / (double) img.getHeight(observer);
+ if( scaleX == 0 || scaleY == 0 )
+ return true;
+
+ return drawImage(img, new AffineTransform(scaleX, 0f, 0f, scaleY, x, y),
+ bgcolor, observer);
+ }
+
+ public boolean drawImage(Image img, int x, int y, int width, int height,
+ ImageObserver observer)
+ {
+ return drawImage(img, x, y, width, height, null, observer);
+ }
+
+ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2, Color bgcolor,
+ ImageObserver observer)
+ {
+ if (img == null)
+ return false;
+
+ int sourceWidth = sx2 - sx1;
+ int sourceHeight = sy2 - sy1;
+
+ int destWidth = dx2 - dx1;
+ int destHeight = dy2 - dy1;
+
+ if(destWidth == 0 || destHeight == 0 || sourceWidth == 0 ||
+ sourceHeight == 0)
+ return true;
+
+ double scaleX = destWidth / (double) sourceWidth;
+ double scaleY = destHeight / (double) sourceHeight;
+
+ // FIXME: Avoid using an AT if possible here - it's at least twice as slow.
+
+ Shape oldClip = getClip();
+ int cx, cy, cw, ch;
+ if( dx1 < dx2 )
+ { cx = dx1; cw = dx2 - dx1; }
+ else
+ { cx = dx2; cw = dx1 - dx2; }
+ if( dy1 < dy2 )
+ { cy = dy1; ch = dy2 - dy1; }
+ else
+ { cy = dy2; ch = dy1 - dy2; }
+
+ clipRect( cx, cy, cw, ch );
+
+ AffineTransform tx = new AffineTransform();
+ tx.translate( dx1 - sx1*scaleX, dy1 - sy1*scaleY );
+ tx.scale( scaleX, scaleY );
+
+ boolean retval = drawImage(img, tx, bgcolor, observer);
+ setClip( oldClip );
+ return retval;
+ }
+
+ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ ImageObserver observer)
+ {
+ return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, observer);
+ }
+
+ /**
+ * Optimized method for drawing a CairoSurface onto this graphics context.
+ *
+ * @param surface The surface to draw.
+ * @param tx The transformation matrix (cannot be null).
+ * @param alpha The alpha value to paint with ( 0 <= alpha <= 1).
+ * @param interpolation The interpolation type.
+ */
+ protected void drawCairoSurface(CairoSurface surface, AffineTransform tx,
+ double alpha, int interpolation)
+ {
+ // Find offset required if this surface is a sub-raster, and append offset
+ // to transformation.
+ if (surface.getSampleModelTranslateX() != 0
+ || surface.getSampleModelTranslateY() != 0)
+ {
+ Point2D origin = new Point2D.Double(0, 0);
+ Point2D offset = new Point2D.Double(surface.getSampleModelTranslateX(),
+ surface.getSampleModelTranslateY());
+
+ tx.transform(origin, origin);
+ tx.transform(offset, offset);
+
+ tx.translate(offset.getX() - origin.getX(),
+ offset.getY() - origin.getY());
+ }
+
+ // Find dimensions of this surface relative to the root parent surface
+ Rectangle bounds = new Rectangle(-surface.getSampleModelTranslateX(),
+ -surface.getSampleModelTranslateY(),
+ surface.width, surface.height);
+
+ // Clip to the translated image
+ // We use direct cairo methods to avoid the overhead of maintaining a
+ // java copy of the clip, since we will be reverting it immediately
+ // after drawing
+ Shape newBounds = tx.createTransformedShape(bounds);
+ cairoSave(nativePointer);
+ walkPath(newBounds.getPathIterator(null), false);
+ cairoClip(nativePointer);
+
+ // Draw the surface
+ try
+ {
+ double[] i2u = new double[6];
+ tx.createInverse().getMatrix(i2u);
+ surface.nativeDrawSurface(surface.surfacePointer, nativePointer, i2u,
+ alpha, interpolation);
+ }
+ catch (NoninvertibleTransformException ex)
+ {
+ // This should never happen(?), so we don't need to do anything here.
+ ;
+ }
+
+ // Restore clip
+ cairoRestore(nativePointer);
+ }
+
+
+ ///////////////////////// TEXT METHODS ////////////////////////////////////
+
+ public void drawString(String str, float x, float y)
+ {
+ if (str == null || str.length() == 0)
+ return;
+ GdkFontPeer fontPeer = (GdkFontPeer) font.getPeer();
+ TextLayout tl = (TextLayout) fontPeer.textLayoutCache.get(str);
+ if (tl == null)
+ {
+ tl = new TextLayout( str, getFont(), getFontRenderContext() );
+ fontPeer.textLayoutCache.put(str, tl);
+ }
+
+ // Set antialias to text_antialiasing, and set the ignoreAA flag so that
+ // the setting doesn't get overridden in a draw() or fill() call.
+ setAntialias(!hints.get(RenderingHints.KEY_TEXT_ANTIALIASING)
+ .equals(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF));
+ ignoreAA = true;
+
+ tl.draw(this, x, y);
+ ignoreAA = false;
+ }
+
+ public void drawString(String str, int x, int y)
+ {
+ drawString (str, (float) x, (float) y);
+ }
+
+ public void drawString(AttributedCharacterIterator ci, int x, int y)
+ {
+ drawString (ci, (float) x, (float) y);
+ }
+
+ public void drawGlyphVector(GlyphVector gv, float x, float y)
+ {
+ double alpha = 1.0;
+
+ if( gv.getNumGlyphs() <= 0 )
+ return;
+
+ if (customPaint)
+ setCustomPaint(gv.getOutline().getBounds());
+
+ if (comp instanceof AlphaComposite)
+ alpha = ((AlphaComposite) comp).getAlpha();
+
+ setAntialias(!hints.get(RenderingHints.KEY_TEXT_ANTIALIASING)
+ .equals(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF));
+ ignoreAA = true;
+
+ if (gv instanceof FreetypeGlyphVector && alpha == 1.0
+ && !((FreetypeGlyphVector)gv).hasTransforms())
+ {
+ int n = gv.getNumGlyphs ();
+ int[] codes = gv.getGlyphCodes (0, n, null);
+ long[] fontset = ((FreetypeGlyphVector)gv).getGlyphFonts (0, n, null);
+ float[] positions = gv.getGlyphPositions (0, n, null);
+
+ setFont (gv.getFont ());
+ GdkFontPeer fontPeer = (GdkFontPeer) font.getPeer();
+ synchronized (fontPeer)
+ {
+ cairoDrawGlyphVector(nativePointer, fontPeer,
+ x, y, n, codes, positions, fontset);
+ }
+ }
+ else
+ {
+ translate(x, y);
+ fill(gv.getOutline());
+ translate(-x, -y);
+ }
+
+ ignoreAA = false;
+ }
+
+ public void drawString(AttributedCharacterIterator ci, float x, float y)
+ {
+ GlyphVector gv = getFont().createGlyphVector(getFontRenderContext(), ci);
+ drawGlyphVector(gv, x, y);
+ }
+
+ /**
+ * Should perhaps be contexct dependent, but this is left for now as an
+ * overloadable default implementation.
+ */
+ public FontRenderContext getFontRenderContext()
+ {
+ return new FontRenderContext(transform, true, true);
+ }
+
+ // Until such time as pango is happy to talk directly to cairo, we
+ // actually need to redirect some calls from the GtkFontPeer and
+ // GtkFontMetrics into the drawing kit and ask cairo ourselves.
+
+ public FontMetrics getFontMetrics()
+ {
+ return getFontMetrics(getFont());
+ }
+
+ public FontMetrics getFontMetrics(Font f)
+ {
+ return ((GdkFontPeer) f.getPeer()).getFontMetrics(f);
+ }
+
+ public void setFont(Font f)
+ {
+ // Sun's JDK does not throw NPEs, instead it leaves the current setting
+ // unchanged. So do we.
+ if (f == null)
+ return;
+
+ if (f.getPeer() instanceof GdkFontPeer)
+ font = f;
+ else
+ font =
+ ((ClasspathToolkit)(Toolkit.getDefaultToolkit()))
+ .getFont(f.getName(), f.getAttributes());
+
+ GdkFontPeer fontpeer = (GdkFontPeer) getFont().getPeer();
+ synchronized (fontpeer)
+ {
+ cairoSetFont(nativePointer, fontpeer);
+ }
+ }
+
+ public Font getFont()
+ {
+ if (font == null)
+ return new Font("SansSerif", Font.PLAIN, 12);
+ return font;
+ }
+
+ /////////////////////// MISC. PUBLIC METHODS /////////////////////////////////
+
+ public boolean hit(Rectangle rect, Shape s, boolean onStroke)
+ {
+ if( onStroke )
+ {
+ Shape stroked = stroke.createStrokedShape( s );
+ return stroked.intersects( (double)rect.x, (double)rect.y,
+ (double)rect.width, (double)rect.height );
+ }
+ return s.intersects( (double)rect.x, (double)rect.y,
+ (double)rect.width, (double)rect.height );
+ }
+
+ public String toString()
+ {
+ return (getClass().getName()
+ + "[font=" + getFont().toString()
+ + ",color=" + fg.toString()
+ + "]");
+ }
+
+ ///////////////////////// PRIVATE METHODS ///////////////////////////////////
+
+ /**
+ * All the drawImage() methods eventually get delegated here if the image
+ * is not a Cairo surface.
+ *
+ * @param bgcolor - if non-null draws the background color before
+ * drawing the image.
+ */
+ private boolean drawRaster(ColorModel cm, Raster r,
+ AffineTransform imageToUser, Color bgcolor)
+ {
+ if (r == null)
+ return false;
+
+ SampleModel sm = r.getSampleModel();
+ DataBuffer db = r.getDataBuffer();
+
+ if (db == null || sm == null)
+ return false;
+
+ if (cm == null)
+ cm = ColorModel.getRGBdefault();
+
+ double[] i2u = new double[6];
+ if (imageToUser != null)
+ imageToUser.getMatrix(i2u);
+ else
+ {
+ i2u[0] = 1;
+ i2u[1] = 0;
+ i2u[2] = 0;
+ i2u[3] = 1;
+ i2u[4] = 0;
+ i2u[5] = 0;
+ }
+
+ int[] pixels = findSimpleIntegerArray(cm, r);
+
+ if (pixels == null)
+ {
+ // FIXME: I don't think this code will work correctly with a non-RGB
+ // MultiPixelPackedSampleModel. Although this entire method should
+ // probably be rewritten to better utilize Cairo's different supported
+ // data formats.
+ if (sm instanceof MultiPixelPackedSampleModel)
+ {
+ pixels = r.getPixels(0, 0, r.getWidth(), r.getHeight(), pixels);
+ for (int i = 0; i < pixels.length; i++)
+ pixels[i] = cm.getRGB(pixels[i]);
+ }
+ else
+ {
+ pixels = new int[r.getWidth() * r.getHeight()];
+ for (int i = 0; i < pixels.length; i++)
+ pixels[i] = cm.getRGB(db.getElem(i));
+ }
+ }
+
+ // Change all transparent pixels in the image to the specified bgcolor,
+ // or (if there's no alpha) fill in an alpha channel so that it paints
+ // correctly.
+ if (cm.hasAlpha())
+ {
+ if (bgcolor != null && cm.hasAlpha())
+ for (int i = 0; i < pixels.length; i++)
+ {
+ if (cm.getAlpha(pixels[i]) == 0)
+ pixels[i] = bgcolor.getRGB();
+ }
+ }
+ else
+ for (int i = 0; i < pixels.length; i++)
+ pixels[i] |= 0xFF000000;
+
+ double alpha = 1.0;
+ if (comp instanceof AlphaComposite)
+ alpha = ((AlphaComposite) comp).getAlpha();
+
+ drawPixels(nativePointer, pixels, r.getWidth(), r.getHeight(),
+ r.getWidth(), i2u, alpha, getInterpolation());
+
+ // Cairo seems to lose the current color which must be restored.
+ updateColor();
+
+ return true;
+ }
+
+ /**
+ * Shifts an x-coordinate by 0.5 in device space.
+ */
+ private double shiftX(double coord, boolean doShift)
+ {
+ if (doShift)
+ {
+ double shift = 0.5;
+ if (!transform.isIdentity())
+ shift /= transform.getScaleX();
+ return (coord + shift);
+ }
+ else
+ return coord;
+ }
+
+ /**
+ * Shifts a y-coordinate by 0.5 in device space.
+ */
+ private double shiftY(double coord, boolean doShift)
+ {
+ if (doShift)
+ {
+ double shift = 0.5;
+ if (!transform.isIdentity())
+ shift /= transform.getScaleY();
+ return (coord + shift);
+ }
+ else
+ return coord;
+ }
+
+ /**
+ * Adds a pathIterator to the current Cairo path, also sets the cairo winding rule.
+ */
+ private void walkPath(PathIterator p, boolean doShift)
+ {
+ double x = 0;
+ double y = 0;
+ double[] coords = new double[6];
+
+ cairoSetFillRule(nativePointer, p.getWindingRule());
+ for (; ! p.isDone(); p.next())
+ {
+ int seg = p.currentSegment(coords);
+ switch (seg)
+ {
+ case PathIterator.SEG_MOVETO:
+ x = shiftX(coords[0], doShift);
+ y = shiftY(coords[1], doShift);
+ cairoMoveTo(nativePointer, x, y);
+ break;
+ case PathIterator.SEG_LINETO:
+ x = shiftX(coords[0], doShift);
+ y = shiftY(coords[1], doShift);
+ cairoLineTo(nativePointer, x, y);
+ break;
+ case PathIterator.SEG_QUADTO:
+ // splitting a quadratic bezier into a cubic:
+ // see: http://pfaedit.sourceforge.net/bezier.html
+ double x1 = x + (2.0 / 3.0) * (shiftX(coords[0], doShift) - x);
+ double y1 = y + (2.0 / 3.0) * (shiftY(coords[1], doShift) - y);
+
+ double x2 = x1 + (1.0 / 3.0) * (shiftX(coords[2], doShift) - x);
+ double y2 = y1 + (1.0 / 3.0) * (shiftY(coords[3], doShift) - y);
+
+ x = shiftX(coords[2], doShift);
+ y = shiftY(coords[3], doShift);
+ cairoCurveTo(nativePointer, x1, y1, x2, y2, x, y);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ x = shiftX(coords[4], doShift);
+ y = shiftY(coords[5], doShift);
+ cairoCurveTo(nativePointer, shiftX(coords[0], doShift),
+ shiftY(coords[1], doShift),
+ shiftX(coords[2], doShift),
+ shiftY(coords[3], doShift), x, y);
+ break;
+ case PathIterator.SEG_CLOSE:
+ cairoClosePath(nativePointer);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Used by setRenderingHints()
+ */
+ private Map<RenderingHints.Key, Object> getDefaultHints()
+ {
+ HashMap<RenderingHints.Key, Object> defaultHints =
+ new HashMap<RenderingHints.Key, Object>();
+
+ defaultHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
+
+ defaultHints.put(RenderingHints.KEY_STROKE_CONTROL,
+ RenderingHints.VALUE_STROKE_DEFAULT);
+
+ defaultHints.put(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
+
+ defaultHints.put(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_OFF);
+
+ defaultHints.put(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_DEFAULT);
+
+ return defaultHints;
+ }
+
+ /**
+ * Used by drawRaster and GdkPixbufDecoder
+ */
+ public static int[] findSimpleIntegerArray (ColorModel cm, Raster raster)
+ {
+ if (cm == null || raster == null)
+ return null;
+
+ if (! cm.getColorSpace().isCS_sRGB())
+ return null;
+
+ if (! (cm instanceof DirectColorModel))
+ return null;
+
+ DirectColorModel dcm = (DirectColorModel) cm;
+
+ if (dcm.getRedMask() != 0x00FF0000 || dcm.getGreenMask() != 0x0000FF00
+ || dcm.getBlueMask() != 0x000000FF)
+ return null;
+
+ if (! (raster instanceof WritableRaster))
+ return null;
+
+ if (raster.getSampleModel().getDataType() != DataBuffer.TYPE_INT)
+ return null;
+
+ if (! (raster.getDataBuffer() instanceof DataBufferInt))
+ return null;
+
+ DataBufferInt db = (DataBufferInt) raster.getDataBuffer();
+
+ if (db.getNumBanks() != 1)
+ return null;
+
+ // Finally, we have determined that this is a single bank, [A]RGB-int
+ // buffer in sRGB space. It's worth checking all this, because it means
+ // that cairo can paint directly into the data buffer, which is very
+ // fast compared to all the normal copying and converting.
+
+ return db.getData();
+ }
+
+ /**
+ * Helper method to transform the clip. This is called by the various
+ * transformation-manipulation methods to update the clip (which is in
+ * userspace) accordingly.
+ *
+ * The transform usually is the inverse transform that was applied to the
+ * graphics object.
+ *
+ * @param t the transform to apply to the clip
+ */
+ private void updateClip(AffineTransform t)
+ {
+ if (clip == null)
+ return;
+
+ // If the clip is a rectangle, and the transformation preserves the shape
+ // (translate/stretch only), then keep the clip as a rectangle
+ double[] matrix = new double[4];
+ t.getMatrix(matrix);
+ if (clip instanceof Rectangle2D && matrix[1] == 0 && matrix[2] == 0)
+ {
+ Rectangle2D rect = (Rectangle2D)clip;
+ double[] origin = new double[] {rect.getX(), rect.getY()};
+ double[] dimensions = new double[] {rect.getWidth(), rect.getHeight()};
+ t.transform(origin, 0, origin, 0, 1);
+ t.deltaTransform(dimensions, 0, dimensions, 0, 1);
+ rect.setRect(origin[0], origin[1], dimensions[0], dimensions[1]);
+ }
+ else
+ {
+ if (! (clip instanceof GeneralPath))
+ clip = new GeneralPath(clip);
+
+ GeneralPath p = (GeneralPath) clip;
+ p.transform(t);
+ }
+ }
+
+ private static Rectangle computeIntersection(int x, int y, int w, int h,
+ Rectangle rect)
+ {
+ int x2 = rect.x;
+ int y2 = rect.y;
+ int w2 = rect.width;
+ int h2 = rect.height;
+
+ int dx = (x > x2) ? x : x2;
+ int dy = (y > y2) ? y : y2;
+ int dw = (x + w < x2 + w2) ? (x + w - dx) : (x2 + w2 - dx);
+ int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy);
+
+ if (dw >= 0 && dh >= 0)
+ rect.setBounds(dx, dy, dw, dh);
+ else
+ rect.setBounds(0, 0, 0, 0);
+
+ return rect;
+ }
+
+ static Rectangle2D getTransformedBounds(Rectangle2D bounds, AffineTransform tx)
+ {
+ double x1 = bounds.getX();
+ double x2 = bounds.getX() + bounds.getWidth();
+ double x3 = x1;
+ double x4 = x2;
+ double y1 = bounds.getY();
+ double y2 = y1;
+ double y3 = bounds.getY() + bounds.getHeight();
+ double y4 = y3;
+
+ double[] points = new double[] {x1, y1, x2, y2, x3, y3, x4, y4};
+ tx.transform(points, 0, points, 0, 4);
+
+ double minX = points[0];
+ double maxX = minX;
+ double minY = points[1];
+ double maxY = minY;
+ for (int i = 0; i < 8; i++)
+ {
+ if (points[i] < minX)
+ minX = points[i];
+ if (points[i] > maxX)
+ maxX = points[i];
+ i++;
+
+ if (points[i] < minY)
+ minY = points[i];
+ if (points[i] > maxY)
+ maxY = points[i];
+ }
+
+ return new Rectangle2D.Double(minX, minY, (maxX - minX), (maxY - minY));
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java
new file mode 100644
index 000000000..71f6638e4
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java
@@ -0,0 +1,428 @@
+/* CairoSurface.java
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.java.awt.Buffers;
+
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DirectColorModel;
+import java.awt.image.Raster;
+import java.awt.image.RasterFormatException;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.awt.image.WritableRaster;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import java.util.Hashtable;
+
+/**
+ * CairoSurface - wraps a Cairo surface.
+ *
+ * @author Sven de Marothy
+ */
+public class CairoSurface extends WritableRaster
+{
+ int width = -1, height = -1;
+
+ /**
+ * The native pointer to the Cairo surface.
+ */
+ long surfacePointer;
+
+ /**
+ * Whether the data buffer is shared between java and cairo.
+ */
+ boolean sharedBuffer;
+
+ // FIXME: use only the cairoCM_pre colormodel
+ // since that's what Cairo really uses (is there a way to do this cheaply?
+ // we use a non-multiplied model most of the time to avoid costly coercion
+ // operations...)
+ static ColorModel cairoColorModel = new DirectColorModel(32, 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF,
+ 0xFF000000);
+
+ static ColorModel cairoCM_pre = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+ 32, 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF,
+ 0xFF000000,
+ true,
+ Buffers.smallestAppropriateTransferType(32));
+
+ // This CM corresponds to the CAIRO_FORMAT_RGB24 type in Cairo
+ static ColorModel cairoCM_opaque = new DirectColorModel(24, 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF);
+ /**
+ * Allocates and clears the buffer and creates the cairo surface.
+ * @param width - the image size
+ * @param height - the image size
+ * @param stride - the buffer row stride. (in ints)
+ */
+ private native void create(int width, int height, int stride, int[] buf);
+
+ /**
+ * Destroys the cairo surface and frees the buffer.
+ */
+ private native void destroy(long surfacePointer, int[] buf);
+
+ /**
+ * Draws this image to a given CairoGraphics context,
+ * with an affine transform given by i2u.
+ */
+ public native void nativeDrawSurface(long surfacePointer, long contextPointer,
+ double[] i2u, double alpha,
+ int interpolation);
+
+ /**
+ * Synchronizes the image's data buffers, copying any changes made in the
+ * Java array into the native array.
+ *
+ * This method should only be called if (sharedBuffers == false).
+ */
+ native void syncNativeToJava(long surfacePointer, int[] buffer);
+
+ /**
+ * Synchronizes the image's data buffers, copying any changes made in the
+ * native array into the Java array.
+ *
+ * This method should only be called if (sharedBuffers == false).
+ */
+ native void syncJavaToNative(long surfacePointer, int[] buffer);
+
+ /**
+ * Return the buffer, with the sample values of each pixel reversed
+ * (ie, in ABGR instead of ARGB).
+ *
+ * @return A pointer to a flipped buffer. The memory is allocated in native
+ * code, and must be explicitly freed when it is no longer needed.
+ */
+ native long getFlippedBuffer(long surfacePointer);
+
+ /**
+ * Create a cairo_surface_t with specified width and height.
+ * The format will be ARGB32 with premultiplied alpha and native bit
+ * and word ordering.
+ */
+ public CairoSurface(int width, int height)
+ {
+ this(0, 0, width, height);
+ }
+
+ public CairoSurface(int x, int y, int width, int height)
+ {
+ super(createCairoSampleModel(width, height), null, new Point(x, y));
+
+ if(width <= 0 || height <= 0)
+ throw new IllegalArgumentException("Image must be at least 1x1 pixels.");
+
+ this.width = width;
+ this.height = height;
+ dataBuffer = new DataBufferInt(width * height);
+ create(width, height, width, getData());
+
+ if(surfacePointer == 0)
+ throw new Error("Could not allocate bitmap.");
+ }
+
+ /**
+ * Create a Cairo Surface that is a subimage of another Cairo Surface
+ */
+ public CairoSurface(SampleModel sm, CairoSurface parent, Rectangle bounds,
+ Point origin)
+ {
+ super(sm, parent.dataBuffer, bounds, origin, parent);
+
+ this.width = super.width;
+ this.height = super.height;
+ this.surfacePointer = parent.surfacePointer;
+ this.sharedBuffer = parent.sharedBuffer;
+ this.dataBuffer = parent.dataBuffer;
+ }
+
+ /**
+ * Create a cairo_surface_t from a GtkImage instance.
+ * (data is copied, not shared)
+ */
+ CairoSurface(GtkImage image)
+ {
+ this(image.width, image.height);
+
+ // Copy the pixel data from the GtkImage.
+ int[] data = image.getPixels();
+
+ // Swap ordering from GdkPixbuf to Cairo
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
+ {
+ for (int i = 0; i < data.length; i++ )
+ {
+ // On a big endian system we get a RRGGBBAA data array.
+ int alpha = data[i] & 0xFF;
+ if( alpha == 0 ) // I do not know why we need this, but it works.
+ data[i] = 0;
+ else
+ {
+ // Cairo needs a ARGB32 native array.
+ data[i] = (data[i] >>> 8) | (alpha << 24);
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < data.length; i++ )
+ {
+ // On a little endian system we get a AABBGGRR data array.
+ int alpha = data[i] & 0xFF000000;
+ if( alpha == 0 ) // I do not know why we need this, but it works.
+ data[i] = 0;
+ else
+ {
+ int b = (data[i] & 0xFF0000) >> 16;
+ int g = (data[i] & 0xFF00);
+ int r = (data[i] & 0xFF) << 16;
+ // Cairo needs a ARGB32 native array.
+ data[i] = alpha | r | g | b;
+ }
+ }
+ }
+
+ System.arraycopy(data, 0, getData(), 0, data.length);
+ }
+
+ /**
+ * Dispose of the native data.
+ */
+ public void dispose()
+ {
+ if(surfacePointer != 0 && parent == null)
+ destroy(surfacePointer, getData());
+ }
+
+ /**
+ * Call dispose() to clean up any native resources allocated.
+ */
+ protected void finalize()
+ {
+ dispose();
+ }
+
+ /**
+ * Return a GtkImage from this Cairo surface.
+ */
+ public GtkImage getGtkImage()
+ {
+ return new GtkImage(width, height, getFlippedBuffer(surfacePointer));
+ }
+
+ /**
+ * Convenience method to quickly grab the data array backing this Raster.
+ *
+ * @return The array behind the databuffer.
+ */
+ public int[] getData()
+ {
+ return ((DataBufferInt)dataBuffer).getData();
+ }
+
+ /**
+ * Returns a BufferedImage backed by a Cairo surface.
+ */
+ public static BufferedImage getBufferedImage(int width, int height)
+ {
+ return getBufferedImage(new CairoSurface(width, height));
+ }
+
+ /**
+ * Returns a BufferedImage backed by a Cairo surface,
+ * created from a GtkImage.
+ */
+ public static BufferedImage getBufferedImage(GtkImage image)
+ {
+ return getBufferedImage(new CairoSurface(image));
+ }
+
+ /**
+ * Returns a BufferedImage backed by a Cairo surface.
+ */
+ public static BufferedImage getBufferedImage(CairoSurface surface)
+ {
+ return new BufferedImage(cairoColorModel, surface,
+ cairoColorModel.isAlphaPremultiplied(),
+ new Hashtable());
+ }
+
+ /**
+ * Return a Graphics2D drawing to the CairoSurface.
+ */
+ public Graphics2D getGraphics()
+ {
+ return new CairoSurfaceGraphics(this);
+ }
+
+ ///// Methods used by CairoSurfaceGraphics /////
+ /**
+ * Creates a cairo_t drawing context, returns the pointer as a long.
+ * Used by CairoSurfaceGraphics.
+ */
+ native long nativeNewCairoContext(long surfacePointer);
+
+ public long newCairoContext()
+ {
+ return nativeNewCairoContext(surfacePointer);
+ }
+
+ /**
+ * Copy a portion of this surface to another area on the surface. The given
+ * parameters must be within bounds - count on a segfault otherwise.
+ *
+ * @param x The x coordinate of the area to be copied from.
+ * @param y The y coordinate of the area to be copied from.
+ * @param width The width of the area to be copied.
+ * @param height The height of the area to be copied.
+ * @param dx The destination x coordinate.
+ * @param dy The destination y coordinate.
+ * @param stride The scanline stride.
+ */
+ public void copyAreaNative(int x, int y, int width,
+ int height, int dx, int dy, int stride)
+ {
+ copyAreaNative2(surfacePointer, x, y, width, height, dx, dy, stride);
+ }
+ native void copyAreaNative2(long surfacePointer,
+ int x, int y, int width, int height,
+ int dx, int dy, int stride);
+
+ /**
+ * Creates a SampleModel that matches Cairo's native format
+ */
+ protected static SampleModel createCairoSampleModel(int w, int h)
+ {
+ return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, w, h,
+ new int[]{0x00FF0000, 0x0000FF00,
+ 0x000000FF, 0xFF000000});
+ }
+
+ /**
+ * Returns whether this ColorModel is compatible with Cairo's native types.
+ *
+ * @param cm The color model to check.
+ * @return Whether it is compatible.
+ */
+ public static boolean isCompatibleColorModel(ColorModel cm)
+ {
+ return (cm.equals(cairoCM_pre) || cm.equals(cairoCM_opaque) ||
+ cm.equals(cairoColorModel));
+ }
+
+ /**
+ * Returns whether this SampleModel is compatible with Cairo's native types.
+ *
+ * @param sm The sample model to check.
+ * @return Whether it is compatible.
+ */
+ public static boolean isCompatibleSampleModel(SampleModel sm)
+ {
+ return (sm instanceof SinglePixelPackedSampleModel
+ && sm.getDataType() == DataBuffer.TYPE_INT
+ && Arrays.equals(((SinglePixelPackedSampleModel)sm).getBitMasks(),
+ new int[]{0x00FF0000, 0x0000FF00,
+ 0x000000FF, 0xFF000000}));
+ }
+
+ ///// Methods interhited from Raster and WritableRaster /////
+ public Raster createChild(int parentX, int parentY, int width, int height,
+ int childMinX, int childMinY, int[] bandList)
+ {
+ return createWritableChild(parentX, parentY, width, height,
+ childMinX, childMinY, bandList);
+ }
+
+ public WritableRaster createCompatibleWritableRaster()
+ {
+ return new CairoSurface(width, height);
+ }
+
+ public WritableRaster createCompatibleWritableRaster (int x, int y,
+ int w, int h)
+ {
+ return new CairoSurface(x, y, w, h);
+ }
+
+ public Raster createTranslatedChild(int childMinX, int childMinY)
+ {
+ return createWritableTranslatedChild(childMinX, childMinY);
+ }
+
+ public WritableRaster createWritableChild(int parentX, int parentY,
+ int w, int h, int childMinX,
+ int childMinY, int[] bandList)
+ {
+ if (parentX < minX || parentX + w > minX + width
+ || parentY < minY || parentY + h > minY + height)
+ throw new RasterFormatException("Child raster extends beyond parent");
+
+ SampleModel sm = (bandList == null) ?
+ sampleModel :
+ sampleModel.createSubsetSampleModel(bandList);
+
+ return new CairoSurface(sm, this,
+ new Rectangle(childMinX, childMinY, w, h),
+ new Point(sampleModelTranslateX + childMinX - parentX,
+ sampleModelTranslateY + childMinY - parentY));
+ }
+
+ public WritableRaster createWritableTranslatedChild(int x, int y)
+ {
+ int tcx = sampleModelTranslateX - minX + x;
+ int tcy = sampleModelTranslateY - minY + y;
+
+ return new CairoSurface(sampleModel, this,
+ new Rectangle(x, y, width, height),
+ new Point(tcx, tcy));
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
new file mode 100644
index 000000000..a0c6caa9a
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java
@@ -0,0 +1,355 @@
+/* CairoSurfaceGraphics.java
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Toolkit;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.RenderedImage;
+import java.util.Hashtable;
+
+/**
+ * Implementation of Graphics2D on a Cairo surface.
+ */
+public class CairoSurfaceGraphics extends CairoGraphics2D
+{
+ protected CairoSurface surface;
+ private BufferedImage buffer;
+ private long cairo_t;
+
+ /**
+ * Create a graphics context from a cairo surface
+ */
+ public CairoSurfaceGraphics(CairoSurface surface)
+ {
+ this.surface = surface;
+ cairo_t = surface.newCairoContext();
+ setup( cairo_t );
+ setClip(0, 0, surface.width, surface.height);
+ }
+
+ /**
+ * Creates another context from a surface.
+ * Used by create().
+ */
+ private CairoSurfaceGraphics(CairoSurfaceGraphics copyFrom)
+ {
+ surface = copyFrom.surface;
+ cairo_t = surface.newCairoContext();
+ copy( copyFrom, cairo_t );
+ }
+
+ public Graphics create()
+ {
+ return new CairoSurfaceGraphics(this);
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
+ }
+
+ protected Rectangle2D getRealBounds()
+ {
+ return new Rectangle2D.Double(0.0, 0.0, surface.width, surface.height);
+ }
+
+ public void copyAreaImpl(int x, int y, int width, int height, int dx, int dy)
+ {
+ surface.copyAreaNative(x, y, width, height, dx, dy, surface.width);
+ }
+
+ /**
+ * Overloaded methods that do actual drawing need to account for custom
+ * composites
+ */
+ public void draw(Shape s)
+ {
+ if (!surface.sharedBuffer)
+ surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
+ // Find total bounds of shape
+ Rectangle r = findStrokedBounds(s);
+ if (shiftDrawCalls)
+ {
+ r.width++;
+ r.height++;
+ }
+
+ // Do the drawing
+ if (comp == null || comp instanceof AlphaComposite)
+ super.draw(s);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setStroke(this.getStroke());
+ g2d.setColor(this.getColor());
+ g2d.setTransform(transform);
+ g2d.draw(s);
+
+ drawComposite(r.getBounds2D(), null);
+ }
+
+ if (!surface.sharedBuffer)
+ surface.syncNativeToJava(surface.surfacePointer, surface.getData());
+ }
+
+ public void fill(Shape s)
+ {
+ if (!surface.sharedBuffer)
+ surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
+ if (comp == null || comp instanceof AlphaComposite)
+ super.fill(s);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setColor(this.getColor());
+ g2d.setTransform(transform);
+ g2d.fill(s);
+
+ drawComposite(s.getBounds2D(), null);
+ }
+
+ if (!surface.sharedBuffer)
+ surface.syncNativeToJava(surface.surfacePointer, surface.getData());
+ }
+
+ public void drawRenderedImage(RenderedImage image, AffineTransform xform)
+ {
+ if (!surface.sharedBuffer)
+ surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
+ if (comp == null || comp instanceof AlphaComposite)
+ super.drawRenderedImage(image, xform);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.setTransform(transform);
+ g2d.drawRenderedImage(image, xform);
+
+ drawComposite(buffer.getRaster().getBounds(), null);
+ }
+
+ if (!surface.sharedBuffer)
+ surface.syncNativeToJava(surface.surfacePointer, surface.getData());
+ }
+
+ protected boolean drawImage(Image img, AffineTransform xform,
+ Color bgcolor, ImageObserver obs)
+ {
+ if (!surface.sharedBuffer)
+ surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
+ boolean ret;
+ if (comp == null || comp instanceof AlphaComposite)
+ ret = super.drawImage(img, xform, bgcolor, obs);
+
+ else
+ {
+ // Get buffered image of source
+ if( !(img instanceof BufferedImage) )
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ img = Toolkit.getDefaultToolkit().createImage(source);
+ }
+ BufferedImage bImg = (BufferedImage) img;
+
+ // Find translated bounds
+ Rectangle2D bounds = new Rectangle(bImg.getMinX(), bImg.getMinY(),
+ bImg.getWidth(), bImg.getHeight());
+ if (xform != null)
+ bounds = getTransformedBounds(bounds, xform);
+
+ // Create buffer and draw image
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.drawImage(img, xform, obs);
+
+ // Perform compositing
+ ret = drawComposite(bounds, obs);
+ }
+
+ if (!surface.sharedBuffer)
+ surface.syncNativeToJava(surface.surfacePointer, surface.getData());
+
+ return ret;
+ }
+
+ public void drawGlyphVector(GlyphVector gv, float x, float y)
+ {
+ if (!surface.sharedBuffer)
+ surface.syncJavaToNative(surface.surfacePointer, surface.getData());
+
+ if (comp == null || comp instanceof AlphaComposite)
+ super.drawGlyphVector(gv, x, y);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setStroke(this.getStroke());
+ g2d.drawGlyphVector(gv, x, y);
+
+ Rectangle2D bounds = gv.getLogicalBounds();
+ bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
+ bounds.getWidth(), bounds.getHeight());
+ drawComposite(bounds, null);
+ }
+
+ if (!surface.sharedBuffer)
+ surface.syncNativeToJava(surface.surfacePointer, surface.getData());
+ }
+
+ private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
+ {
+ // Find bounds in device space
+ bounds = getTransformedBounds(bounds, transform);
+
+ // Clip bounds by the stored clip, and by the internal buffer
+ Rectangle2D devClip = this.getClipInDevSpace();
+ Rectangle2D.intersect(bounds, devClip, bounds);
+ devClip = new Rectangle(buffer.getMinX(), buffer.getMinY(),
+ buffer.getWidth(), buffer.getHeight());
+ Rectangle2D.intersect(bounds, devClip, bounds);
+
+ // Round bounds as needed, but be careful in our rounding
+ // (otherwise it may leave unpainted stripes)
+ double x = bounds.getX();
+ double y = bounds.getY();
+ double maxX = x + bounds.getWidth();
+ double maxY = y + bounds.getHeight();
+ x = Math.round(x);
+ y = Math.round(y);
+ bounds.setRect(x, y, Math.round(maxX - x), Math.round(maxY - y));
+
+ // Find subimage of internal buffer for updating
+ BufferedImage buffer2 = buffer;
+ if (!bounds.equals(buffer2.getRaster().getBounds()))
+ buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(),
+ (int)bounds.getHeight());
+
+ // Find subimage of main image for updating
+ BufferedImage current = CairoSurface.getBufferedImage(surface);
+ current = current.getSubimage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(),
+ (int)bounds.getHeight());
+
+ // Perform actual composite operation
+ compCtx.compose(buffer2.getRaster(), current.getRaster(),
+ buffer2.getRaster());
+
+ // Set cairo's composite to direct SRC, since we've already done our own
+ // compositing
+ Composite oldcomp = comp;
+ setComposite(AlphaComposite.Src);
+
+ // This MUST call directly into the "action" method in CairoGraphics2D,
+ // not one of the wrappers, to ensure that the composite isn't processed
+ // more than once!
+ boolean rv = super.drawImage(buffer2,
+ AffineTransform.getTranslateInstance(bounds.getX(),
+ bounds.getY()),
+ null, null);
+ setComposite(oldcomp);
+ updateColor();
+ return rv;
+ }
+
+ private void createBuffer()
+ {
+ if (buffer == null)
+ {
+ buffer = new BufferedImage(getBufferCM(),
+ surface.createCompatibleWritableRaster(),
+ getBufferCM().isAlphaPremultiplied(),
+ new Hashtable());
+ }
+ else
+ {
+ Graphics2D g2d = ((Graphics2D)buffer.getGraphics());
+
+ g2d.setBackground(new Color(0,0,0,0));
+ g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
+ }
+ }
+
+ protected ColorModel getNativeCM()
+ {
+ return CairoSurface.cairoCM_pre;
+ }
+
+ protected ColorModel getBufferCM()
+ {
+ return CairoSurface.cairoColorModel;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java
new file mode 100644
index 000000000..50161b2b7
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java
@@ -0,0 +1,941 @@
+/* ComponentGraphics.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.classpath.Pointer;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Toolkit;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.WritableRaster;
+import java.util.Hashtable;
+
+/**
+ * ComponentGraphics - context for drawing directly to a component,
+ * as this is an X drawable, it requires that we use GTK locks.
+ *
+ * This context draws directly to the drawable and requires xrender.
+ */
+public class ComponentGraphics extends CairoGraphics2D
+{
+ private static final boolean hasXRenderExtension = hasXRender();
+
+ private GtkComponentPeer component;
+ protected long cairo_t;
+ private BufferedImage buffer, componentBuffer;
+
+ private static ThreadLocal<Integer> hasLock = new ThreadLocal<Integer>();
+ private static Integer ONE = Integer.valueOf(1);
+
+ ComponentGraphics()
+ {
+ }
+
+ private ComponentGraphics(GtkComponentPeer component)
+ {
+ this.component = component;
+ cairo_t = initState(component);
+ setup( cairo_t );
+ Rectangle bounds = component.awtComponent.getBounds();
+ setClip( new Rectangle( 0, 0, bounds.width, bounds.height) );
+ setBackground(component.awtComponent.getBackground());
+ setColor(component.awtComponent.getForeground());
+ }
+
+ private ComponentGraphics(ComponentGraphics cg)
+ {
+ component = cg.component;
+ cairo_t = initState(component);
+ copy( cg, cairo_t );
+ Rectangle bounds = component.awtComponent.getBounds();
+ setClip( new Rectangle( 0, 0, bounds.width, bounds.height) );
+ setBackground(component.awtComponent.getBackground());
+ setColor(component.awtComponent.getForeground());
+ }
+
+ /**
+ * Creates a cairo_t for the component surface and return it.
+ */
+ private native long initState(GtkComponentPeer component);
+
+ /**
+ * Obtain and hold a GDK lock, which is required for all drawing operations
+ * in this graphics context (since it is backed by an X surface).
+ *
+ * This method causes the GDK locking behaviour to be re-entrant. No race
+ * conditions are caused since a ThreadLocal is used and each thread has its
+ * own lock counter.
+ */
+ private void lock()
+ {
+ Integer i = hasLock.get();
+ if (i == null)
+ {
+ start_gdk_drawing();
+ hasLock.set(ONE);
+ }
+ else
+ hasLock.set(Integer.valueOf(i.intValue() + 1));
+ }
+
+ /**
+ * Release the re-entrant GDK lock.
+ */
+ private void unlock()
+ {
+ Integer i = hasLock.get();
+ if (i == null)
+ throw new IllegalStateException();
+ if (i == ONE)
+ {
+ hasLock.set(null);
+ end_gdk_drawing();
+ }
+ else if (i.intValue() == 2)
+ hasLock.set(ONE);
+ else
+ hasLock.set(Integer.valueOf(i.intValue() - 1));
+ }
+
+ /**
+ * Creates a cairo_t for a volatile image
+ */
+ protected native long initFromVolatile( long pixmapPtr);
+
+ /**
+ * Grab lock
+ */
+ private native void start_gdk_drawing();
+
+ /**
+ * Release lock
+ */
+ private native void end_gdk_drawing();
+
+ /**
+ * Query if the system has the XRender extension.
+ */
+ public static native boolean hasXRender();
+
+ /**
+ * This is a utility method (used by GtkComponentPeer) for grabbing the
+ * image of a component.
+ */
+ private static native Pointer nativeGrab(GtkComponentPeer component);
+
+ private native void copyAreaNative(GtkComponentPeer component, int x, int y,
+ int width, int height, int dx, int dy);
+
+ private native void drawVolatile(GtkComponentPeer component,
+ long vimg, int x, int y,
+ int width, int height, int cx, int cy,
+ int cw, int ch);
+
+ /**
+ * Not really related (moveme?). Utility method used by GtkComponent.
+ */
+ public static GtkImage grab( GtkComponentPeer component )
+ {
+ return new GtkImage( nativeGrab( component ) );
+ }
+
+ /**
+ * Returns a Graphics2D object for a component, either an instance of this
+ * class (if xrender is supported), or a context which copies.
+ */
+ public static Graphics2D getComponentGraphics(GtkComponentPeer component)
+ {
+ if( hasXRenderExtension )
+ return new ComponentGraphics(component);
+
+ Rectangle r = component.awtComponent.getBounds();
+ return new ComponentGraphicsCopy(r.width, r.height, component);
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ return component.getGraphicsConfiguration();
+ }
+
+ public Graphics create()
+ {
+ return new ComponentGraphics(this);
+ }
+
+ protected Rectangle2D getRealBounds()
+ {
+ return component.awtComponent.getBounds();
+ }
+
+ public void copyAreaImpl(int x, int y, int width, int height, int dx, int dy)
+ {
+ copyAreaNative(component, x, y, width, height, dx, dy);
+ }
+
+ /**
+ * Overloaded methods that do actual drawing need to enter the gdk threads
+ * and also do certain things before and after.
+ */
+ public void draw(Shape s)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ super.draw(s);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setStroke(this.getStroke());
+ g2d.setColor(this.getColor());
+ g2d.draw(s);
+
+ drawComposite(s.getBounds2D(), null);
+ }
+ }
+
+ public void fill(Shape s)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ super.fill(s);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setColor(this.getColor());
+ g2d.fill(s);
+
+ drawComposite(s.getBounds2D(), null);
+ }
+ }
+
+ public void drawRenderedImage(RenderedImage image, AffineTransform xform)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ super.drawRenderedImage(image, xform);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.drawRenderedImage(image, xform);
+
+ drawComposite(buffer.getRaster().getBounds(), null);
+ }
+ }
+
+ protected boolean drawImage(Image img, AffineTransform xform,
+ Color bgcolor, ImageObserver obs)
+ {
+ boolean rv;
+ if (comp == null || comp instanceof AlphaComposite)
+ rv = super.drawImage(img, xform, bgcolor, obs);
+
+ else
+ {
+ // Get buffered image of source
+ if( !(img instanceof BufferedImage) )
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ img = Toolkit.getDefaultToolkit().createImage(source);
+ }
+ BufferedImage bImg = (BufferedImage) img;
+
+ // Find translated bounds
+ Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
+ Point2D pt = new Point2D.Double(bImg.getWidth() + bImg.getMinX(),
+ bImg.getHeight() + bImg.getMinY());
+ if (xform != null)
+ {
+ origin = xform.transform(origin, origin);
+ pt = xform.transform(pt, pt);
+ }
+
+ // Create buffer and draw image
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.drawImage(img, xform, obs);
+
+ // Perform compositing
+ rv = drawComposite(new Rectangle2D.Double(origin.getX(),
+ origin.getY(),
+ pt.getX(), pt.getY()),
+ obs);
+ }
+ return rv;
+ }
+
+ public void drawGlyphVector(GlyphVector gv, float x, float y)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ super.drawGlyphVector(gv, x, y);
+
+ else
+ {
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setStroke(this.getStroke());
+ g2d.drawGlyphVector(gv, x, y);
+
+ Rectangle2D bounds = gv.getLogicalBounds();
+ bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
+ bounds.getWidth(), bounds.getHeight());
+ drawComposite(bounds, null);
+ }
+ }
+
+ public boolean drawImage(Image img, int x, int y, ImageObserver observer)
+ {
+ // If it is a GtkVolatileImage with an "easy" transform then
+ // draw directly. Always pass a BufferedImage to super to avoid
+ // deadlock (see Note in CairoGraphics.drawImage()).
+ if (img instanceof GtkVolatileImage)
+ {
+ GtkVolatileImage vimg = (GtkVolatileImage) img;
+ int type = transform.getType();
+ if ((type == AffineTransform.TYPE_IDENTITY
+ || type == AffineTransform.TYPE_TRANSLATION)
+ && (clip == null || clip instanceof Rectangle2D))
+ {
+ Rectangle2D r = (Rectangle2D) clip;
+ if (r == null)
+ r = getRealBounds();
+ x += transform.getTranslateX();
+ y += transform.getTranslateY();
+ drawVolatile(component, vimg.nativePointer,
+ x, y, vimg.width, vimg.height,
+ (int) (r.getX() + transform.getTranslateX()),
+ (int) (r.getY() + transform.getTranslateY()),
+ (int) r.getWidth(),
+ (int) r.getHeight());
+ return true;
+ }
+ else
+ return super.drawImage(vimg.getSnapshot(), x, y, observer);
+ }
+
+ BufferedImage bimg;
+ if (img instanceof BufferedImage)
+ bimg = (BufferedImage) img;
+ else
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source);
+ }
+ return super.drawImage(bimg, x, y, observer);
+ }
+
+ public boolean drawImage(Image img, int x, int y, int width, int height,
+ ImageObserver observer)
+ {
+ // If it is a GtkVolatileImage with an "easy" transform then
+ // draw directly. Always pass a BufferedImage to super to avoid
+ // deadlock (see Note in CairoGraphics.drawImage()).
+ if (img instanceof GtkVolatileImage
+ && (clip == null || clip instanceof Rectangle2D))
+ {
+ GtkVolatileImage vimg = (GtkVolatileImage) img;
+ int type = transform.getType();
+ if ((type == AffineTransform.TYPE_IDENTITY
+ || type == AffineTransform.TYPE_TRANSLATION)
+ && (clip == null || clip instanceof Rectangle2D))
+ {
+ Rectangle2D r = (Rectangle2D) clip;
+ if (r == null)
+ r = getRealBounds();
+ x += transform.getTranslateX();
+ y += transform.getTranslateY();
+ drawVolatile(component, vimg.nativePointer,
+ x, y, width, height,
+ (int) (r.getX() + transform.getTranslateX()),
+ (int) (r.getY() + transform.getTranslateY()),
+ (int) r.getWidth(),
+ (int) r.getHeight());
+ return true;
+ }
+ else
+ return super.drawImage(vimg.getSnapshot(), x, y,
+ width, height, observer);
+ }
+
+ BufferedImage bimg;
+ img = AsyncImage.realImage(img, observer);
+ if (img instanceof BufferedImage)
+ bimg = (BufferedImage) img;
+ else
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source);
+ }
+ return super.drawImage(bimg, x, y, width, height, observer);
+ }
+
+ private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
+ {
+ // Clip source to visible areas that need updating
+ Rectangle2D clip = this.getClipBounds();
+ Rectangle2D.intersect(bounds, clip, bounds);
+ clip = new Rectangle(buffer.getMinX(), buffer.getMinY(),
+ buffer.getWidth(), buffer.getHeight());
+ Rectangle2D.intersect(bounds, clip, bounds);
+
+ BufferedImage buffer2 = buffer;
+ if (!bounds.equals(buffer2.getRaster().getBounds()))
+ buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(),
+ (int)bounds.getHeight());
+
+ // Get destination clip to bounds
+ double[] points = new double[] {bounds.getX(), bounds.getY(),
+ bounds.getMaxX(), bounds.getMaxY()};
+ transform.transform(points, 0, points, 0, 2);
+
+ Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1],
+ points[2] - points[0],
+ points[3] - points[1]);
+
+ Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds);
+
+ // Get current image on the component
+ GtkImage img = grab(component);
+ Graphics gr = componentBuffer.createGraphics();
+ gr.drawImage(img, 0, 0, null);
+ gr.dispose();
+
+ BufferedImage cBuffer = componentBuffer;
+ if (!deviceBounds.equals(cBuffer.getRaster().getBounds()))
+ cBuffer = cBuffer.getSubimage((int)deviceBounds.getX(),
+ (int)deviceBounds.getY(),
+ (int)deviceBounds.getWidth(),
+ (int)deviceBounds.getHeight());
+
+ // Perform actual composite operation
+ compCtx.compose(buffer2.getRaster(), cBuffer.getRaster(),
+ cBuffer.getRaster());
+
+ // This MUST call directly into the "action" method in CairoGraphics2D,
+ // not one of the wrappers, to ensure that the composite isn't processed
+ // more than once!
+ boolean rv = super.drawImage(cBuffer,
+ AffineTransform.getTranslateInstance(bounds.getX(),
+ bounds.getY()),
+ null, null);
+ return rv;
+ }
+
+ private void createBuffer()
+ {
+ if (buffer == null)
+ {
+ WritableRaster rst;
+ rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(component.awtComponent.getWidth(),
+ component.awtComponent.getHeight()),
+ new Point(0,0));
+
+ buffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
+ GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
+ new Hashtable());
+ }
+ else
+ {
+ Graphics2D g2d = ((Graphics2D)buffer.getGraphics());
+
+ g2d.setBackground(new Color(0,0,0,0));
+ g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
+ }
+
+ if (componentBuffer == null)
+ {
+ WritableRaster rst;
+ rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(component.awtComponent.getWidth(),
+ component.awtComponent.getHeight()),
+ new Point(0,0));
+
+ componentBuffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
+ GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
+ new Hashtable());
+ }
+ }
+
+ protected ColorModel getNativeCM()
+ {
+ return GtkVolatileImage.gdkColorModel;
+ }
+
+ /* --- START OVERRIDDEN NATIVE METHODS ----
+ * All native methods in CairoGraphics2D should be overridden here and
+ * enclosed in locks, since the cairo surface is backed by an X surface
+ * in this graphics context and the X surface requires external locking.
+ *
+ * We lock everything "just in case", since it's difficult to know which
+ * calls are and aren't thread-safe. Overriding and locking the native
+ * methods allows superclass code in CairoGraphics2D to execute properly,
+ * without the need to override every single method.
+ *
+ * CAVEAT: if native code obtains a lock (using gdk_threads_enter(), not the
+ * lock() method provided here) and then calls back into Java and one of these
+ * methods ends up being called, we will deadlock. The lock is only reentrant
+ * when called via our lock() method.
+ */
+
+ /* These methods are already locked in the superclass CairoGraphics2D
+ * so they do not need to be overridden:
+ *
+ * public void disposeNative
+ *
+ * protected void cairoDrawGlyphVector
+ *
+ * protected void cairoSetFont
+ */
+
+ @Override
+ protected long init(long pointer)
+ {
+ long ret;
+
+ try
+ {
+ lock();
+ ret = super.init(pointer);
+ }
+ finally
+ {
+ unlock();
+ }
+
+ return ret;
+ }
+
+ @Override
+ protected void drawPixels(long pointer, int[] pixels, int w, int h,
+ int stride, double[] i2u, double alpha,
+ int interpolation)
+ {
+ try
+ {
+ lock();
+ super.drawPixels(pointer, pixels, w, h, stride, i2u, alpha,
+ interpolation);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void setGradient(long pointer, 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)
+ {
+ try
+ {
+ lock();
+ super.setGradient(pointer, x1, y1, x2, y2, r1, g1, b1, a1, r2, g2, b2, a2,
+ cyclic);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void setPaintPixels(long pointer, int[] pixels, int w, int h,
+ int stride, boolean repeat, int x, int y)
+ {
+ try
+ {
+ lock();
+ super.setPaintPixels(pointer, pixels, w, h, stride, repeat, x, y);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoSetMatrix(long pointer, double[] m)
+ {
+ try
+ {
+ lock();
+ super.cairoSetMatrix(pointer, m);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoScale(long pointer, double x, double y)
+ {
+ try
+ {
+ lock();
+ super.cairoScale(pointer, x, y);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoSetOperator(long pointer, int cairoOperator)
+ {
+ try
+ {
+ lock();
+ super.cairoSetOperator(pointer, cairoOperator);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoSetRGBAColor(long pointer, double red, double green,
+ double blue, double alpha)
+ {
+ try
+ {
+ lock();
+ super.cairoSetRGBAColor(pointer, red, green, blue, alpha);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoSetFillRule(long pointer, int cairoFillRule)
+ {
+ try
+ {
+ lock();
+ super.cairoSetFillRule(pointer, cairoFillRule);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoSetLine(long pointer, double width, int cap, int join,
+ double miterLimit)
+ {
+ try
+ {
+ lock();
+ super.cairoSetLine(pointer, width, cap, join, miterLimit);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoSetDash(long pointer, double[] dashes, int ndash,
+ double offset)
+ {
+ try
+ {
+ lock();
+ super.cairoSetDash(pointer, dashes, ndash, offset);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoRectangle(long pointer, double x, double y,
+ double width, double height)
+ {
+ try
+ {
+ lock();
+ super.cairoRectangle(pointer, x, y, width, height);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoArc(long pointer, double x, double y,
+ double radius, double angle1, double angle2)
+ {
+ try
+ {
+ lock();
+ super.cairoArc(pointer, x, y, radius, angle1, angle2);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoSave(long pointer)
+ {
+ try
+ {
+ lock();
+ super.cairoSave(pointer);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoRestore(long pointer)
+ {
+ try
+ {
+ lock();
+ super.cairoRestore(pointer);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoNewPath(long pointer)
+ {
+ try
+ {
+ lock();
+ super.cairoNewPath(pointer);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoClosePath(long pointer)
+ {
+ try
+ {
+ lock();
+ super.cairoClosePath(pointer);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoMoveTo(long pointer, double x, double y)
+ {
+ try
+ {
+ lock();
+ super.cairoMoveTo(pointer, x, y);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoLineTo(long pointer, double x, double y)
+ {
+ try
+ {
+ lock();
+ super.cairoLineTo(pointer, x, y);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoCurveTo(long pointer, double x1, double y1, double x2,
+ double y2, double x3, double y3)
+ {
+ try
+ {
+ lock();
+ super.cairoCurveTo(pointer, x1, y1, x2, y2, x3, y3);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoStroke(long pointer)
+ {
+ try
+ {
+ lock();
+ super.cairoStroke(pointer);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoFill(long pointer, double alpha)
+ {
+ try
+ {
+ lock();
+ super.cairoFill(pointer, alpha);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoClip(long pointer)
+ {
+ try
+ {
+ lock();
+ super.cairoClip(pointer);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoResetClip(long pointer)
+ {
+ try
+ {
+ lock();
+ super.cairoResetClip(pointer);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void cairoSetAntialias(long pointer, boolean aa)
+ {
+ try
+ {
+ lock();
+ super.cairoSetAntialias(pointer, aa);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+
+ @Override
+ protected void drawCairoSurface(CairoSurface surface, AffineTransform tx,
+ double alpha, int interpolation)
+ {
+ try
+ {
+ lock();
+ super.drawCairoSurface(surface, tx, alpha, interpolation);
+ }
+ finally
+ {
+ unlock();
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java
new file mode 100644
index 000000000..a73012d9f
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphicsCopy.java
@@ -0,0 +1,122 @@
+/* ComponentGraphicsCopy.java
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.image.RenderedImage;
+import java.awt.image.ImageObserver;
+
+/**
+ * Implementation of Graphics2D for Components for servers which
+ * do not have xrender.
+ *
+ * A mirrored GtkImage of the component is stored in memory
+ * and copied back. Yay.
+ */
+public class ComponentGraphicsCopy extends CairoSurfaceGraphics
+{
+ private GtkComponentPeer component;
+
+ /**
+ * GtkImage sharing its data buffer with this Cairo surface.
+ */
+ private GtkImage gtkimage;
+
+ private int width, height;
+
+ native void getPixbuf( GtkComponentPeer component, GtkImage image );
+
+ native void copyPixbuf( GtkComponentPeer component, GtkImage image,
+ int x, int y, int w, int h );
+
+ public ComponentGraphicsCopy(int width, int height,
+ GtkComponentPeer component)
+ {
+ super( new CairoSurface( width, height ) );
+ this.component = component;
+ this.width = width;
+ this.height = height;
+ gtkimage = surface.getGtkImage();
+ getPixbuf( component, gtkimage );
+ }
+
+ /**
+ * Overloaded methods that do actual drawing need to enter the gdk threads
+ * and also do certain things before and after.
+ */
+ public void draw(Shape s)
+ {
+ super.draw(s);
+ Rectangle r = s.getBounds();
+ copyPixbuf(component, gtkimage, r.x, r.y, r.width, r.height);
+ }
+
+ public void fill(Shape s)
+ {
+ super.fill(s);
+ Rectangle r = s.getBounds();
+ copyPixbuf(component, gtkimage, r.x, r.y, r.width, r.height);
+ }
+
+ public void drawRenderedImage(RenderedImage image, AffineTransform xform)
+ {
+ super.drawRenderedImage(image, xform);
+ copyPixbuf(component, gtkimage, 0, 0, width, height);
+ }
+
+ protected boolean drawImage(Image img, AffineTransform xform,
+ Color bgcolor, ImageObserver obs)
+ {
+ boolean rv = super.drawImage(img, xform, bgcolor, obs);
+ copyPixbuf(component, gtkimage, 0, 0, width, height);
+ return rv;
+ }
+
+ public void drawGlyphVector(GlyphVector gv, float x, float y)
+ {
+ super.drawGlyphVector(gv, x, y);
+ Rectangle r = gv.getPixelBounds(getFontRenderContext(), x , y);
+ copyPixbuf(component, gtkimage, r.x, r.y, r.width, r.height);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java b/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
new file mode 100644
index 000000000..8fd734799
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
@@ -0,0 +1,630 @@
+/* FreetypeGlyphVector.java
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Font;
+import java.awt.Shape;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphJustificationInfo;
+import java.awt.font.GlyphMetrics;
+import java.awt.font.GlyphVector;
+import java.awt.font.TextAttribute;
+import java.awt.font.TransformAttribute;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.Arrays;
+
+public class FreetypeGlyphVector extends GlyphVector
+{
+ /**
+ * The associated font and its peer.
+ */
+ private Font font;
+ private GdkFontPeer peer; // ATTN: Accessed from native code.
+
+ private Rectangle2D logicalBounds;
+
+ private float[] glyphPositions;
+ /**
+ * The string represented by this GlyphVector.
+ */
+ private String s;
+
+ /**
+ * The font render context
+ */
+ private FontRenderContext frc;
+
+ /**
+ * The total # of glyphs.
+ */
+ private int nGlyphs;
+
+ /**
+ * The glyph codes
+ */
+ private int[] glyphCodes;
+
+ /**
+ * The set of fonts used in this glyph vector.
+ */
+ private long[] fontSet = null;
+
+ /**
+ * Glyph transforms. Supports all transform operations.
+ *
+ * The identity transform should not be stored in this array; use a null
+ * instead (will result in performance improvements).
+ */
+ private AffineTransform[] glyphTransforms;
+
+ private GlyphMetrics[] metricsCache;
+
+ private native void dispose(long[] fonts);
+
+ /**
+ * Returns a pointer to the native PangoFcFont object.
+ *
+ * The object will be referenced with g_object_ref n times before being
+ * returned, and must be unreferenced a corresponding number of times.
+ *
+ * @param n Number of times to reference the object.
+ * @return Pointer to the native default font.
+ */
+ private native long getNativeFontPointer(int n);
+
+ /**
+ * Create a glyphvector from a given (Freetype) font and a String.
+ */
+ public FreetypeGlyphVector(Font f, String s, FontRenderContext frc)
+ {
+ this(f, s.toCharArray(), 0, s.length(), frc, Font.LAYOUT_LEFT_TO_RIGHT);
+ }
+
+ /**
+ * Create a glyphvector from a given (Freetype) font and a String.
+ */
+ public FreetypeGlyphVector(Font f, char[] chars, int start, int len,
+ FontRenderContext frc, int flags)
+ {
+ this.s = new String(chars, start, len);
+
+ this.font = f;
+ this.frc = frc;
+ if( !(font.getPeer() instanceof GdkFontPeer ) )
+ throw new IllegalArgumentException("Not a valid font.");
+ peer = (GdkFontPeer)font.getPeer();
+
+ getGlyphs();
+ if( flags == Font.LAYOUT_RIGHT_TO_LEFT )
+ {
+ // reverse the glyph ordering.
+ int[] temp = new int[ nGlyphs ];
+ for(int i = 0; i < nGlyphs; i++)
+ temp[i] = glyphCodes[nGlyphs - i - 1];
+ glyphCodes = temp;
+ }
+ performDefaultLayout();
+ }
+
+ /**
+ * Create a glyphvector from a given set of glyph codes.
+ */
+ public FreetypeGlyphVector(Font f, int[] codes, FontRenderContext frc)
+ {
+ this.font = f;
+ this.frc = frc;
+ if( !(font.getPeer() instanceof GdkFontPeer ) )
+ throw new IllegalArgumentException("Not a valid font.");
+ peer = (GdkFontPeer)font.getPeer();
+
+ glyphCodes = new int[ codes.length ];
+ System.arraycopy(codes, 0, glyphCodes, 0, codes.length);
+ nGlyphs = glyphCodes.length;
+
+ if (fontSet == null)
+ {
+ fontSet = new long[nGlyphs];
+ Arrays.fill(fontSet, getNativeFontPointer(nGlyphs));
+ }
+
+ performDefaultLayout();
+ }
+
+ /**
+ * Cloning constructor
+ */
+ private FreetypeGlyphVector( FreetypeGlyphVector gv )
+ {
+ font = gv.font;
+ peer = gv.peer;
+ frc = gv.frc;
+ s = gv.s;
+ nGlyphs = gv.nGlyphs;
+ logicalBounds = gv.logicalBounds.getBounds2D();
+
+ if( gv.metricsCache != null )
+ {
+ metricsCache = new GlyphMetrics[ nGlyphs ];
+ System.arraycopy(gv.metricsCache, 0, metricsCache, 0, nGlyphs);
+ }
+
+ glyphCodes = new int[ nGlyphs ];
+ fontSet = new long[nGlyphs];
+ glyphPositions = new float[(nGlyphs + 1) * 2];
+ glyphTransforms = new AffineTransform[ nGlyphs ];
+ Arrays.fill(glyphTransforms, null);
+
+ for(int i = 0; i < nGlyphs; i++ )
+ {
+ if (gv.glyphTransforms[i] != null)
+ glyphTransforms[ i ] = new AffineTransform(gv.glyphTransforms[i]);
+ glyphCodes[i] = gv.glyphCodes[ i ];
+ }
+ System.arraycopy(gv.glyphPositions, 0, glyphPositions, 0,
+ glyphPositions.length);
+ System.arraycopy(gv.glyphCodes, 0, glyphCodes, 0, nGlyphs);
+ System.arraycopy(gv.fontSet, 0, fontSet, 0, nGlyphs);
+ }
+
+ public void finalize()
+ {
+ dispose(fontSet);
+ }
+
+ /**
+ * Create the array of glyph codes.
+ */
+ private void getGlyphs()
+ {
+ nGlyphs = s.codePointCount( 0, s.length() );
+ glyphCodes = new int[ nGlyphs ];
+ fontSet = new long[ nGlyphs ];
+ int[] codePoints = new int[ nGlyphs ];
+ int stringIndex = 0;
+
+ for(int i = 0; i < nGlyphs; i++)
+ {
+ codePoints[i] = s.codePointAt( stringIndex );
+ // UTF32 surrogate handling
+ if( codePoints[i] != (int)s.charAt( stringIndex ) )
+ stringIndex ++;
+ stringIndex ++;
+
+ if (Character.isISOControl(codePoints[i]))
+ {
+ // Replace with 'hair space'. Should better be 'zero-width space'
+ // but that doesn't seem to be supported by default font.
+ codePoints[i] = 8202;
+ }
+ }
+
+ getGlyphs( codePoints, glyphCodes, fontSet );
+ }
+
+ /**
+ * Returns the glyph code within the font for a given character
+ */
+ public native void getGlyphs(int[] codepoints, int[] glyphs, long[] fonts);
+
+ /**
+ * Returns the kerning of a glyph pair
+ */
+ private native void getKerning(int leftGlyph, int rightGlyph, long font,
+ float[] p);
+
+ private native double[] getMetricsNative(int glyphCode, long font);
+
+ private native GeneralPath getGlyphOutlineNative(int glyphIndex, long font);
+
+
+ public Object clone()
+ {
+ return new FreetypeGlyphVector( this );
+ }
+
+ /**
+ * Duh, compares two instances.
+ */
+ public boolean equals(GlyphVector gv)
+ {
+ if( ! (gv instanceof FreetypeGlyphVector) )
+ return false;
+
+ return (((FreetypeGlyphVector)gv).font.equals(font) &&
+ ((FreetypeGlyphVector)gv).frc.equals(frc)
+ && ((FreetypeGlyphVector)gv).s.equals(s));
+ }
+
+ /**
+ * Returns the associated Font
+ */
+ public Font getFont()
+ {
+ return font;
+ }
+
+ /**
+ * Returns the associated FontRenderContext
+ */
+ public FontRenderContext getFontRenderContext()
+ {
+ return frc;
+ }
+
+ /**
+ * Layout the glyphs.
+ */
+ public void performDefaultLayout()
+ {
+ logicalBounds = null; // invalidate caches.
+ glyphTransforms = new AffineTransform[nGlyphs];
+ Arrays.fill(glyphTransforms, null);
+ glyphPositions = new float[(nGlyphs + 1) * 2];
+
+ GlyphMetrics gm = null;
+ float x = 0;
+ float y = 0;
+ float[] p = {0.0f, 0.0f};
+ for(int i = 0; i < nGlyphs; i++)
+ {
+ gm = getGlyphMetrics( i );
+ glyphPositions[i*2] = x;
+ glyphPositions[i*2 + 1] = y;
+
+ x += gm.getAdvanceX();
+ y += gm.getAdvanceY();
+
+ // Get the kerning only if it's not the last glyph, and the two glyphs are
+ // using the same font
+ if (i != nGlyphs-1 && fontSet[i] == fontSet[i+1])
+ {
+ getKerning(glyphCodes[i], glyphCodes[i + 1], fontSet[i], p);
+ x += p[0];
+ y += p[1];
+ }
+ }
+ glyphPositions[nGlyphs * 2] = x;
+ glyphPositions[nGlyphs * 2 + 1] = y;
+
+ // Apply any transform that may be in the font's attributes
+ TransformAttribute ta;
+ ta = (TransformAttribute)font.getAttributes().get(TextAttribute.TRANSFORM);
+ if (ta != null)
+ {
+ AffineTransform tx = ta.getTransform();
+
+ // Transform glyph positions
+ tx.transform(glyphPositions, 0, glyphPositions, 0,
+ glyphPositions.length / 2);
+
+ // Also store per-glyph scale/shear/rotate (but not translation)
+ double[] matrix = new double[4];
+ tx.getMatrix(matrix);
+ AffineTransform deltaTx = new AffineTransform(matrix);
+ if (!deltaTx.isIdentity())
+ Arrays.fill(glyphTransforms, deltaTx);
+ }
+ }
+
+ /**
+ * Returns the code of the glyph at glyphIndex;
+ */
+ public int getGlyphCode(int glyphIndex)
+ {
+ return glyphCodes[ glyphIndex ];
+ }
+
+ /**
+ * Returns multiple glyphcodes.
+ */
+ public int[] getGlyphCodes(int beginGlyphIndex, int numEntries,
+ int[] codeReturn)
+ {
+ int[] rval;
+
+ if( codeReturn == null || codeReturn.length < numEntries)
+ rval = new int[ numEntries ];
+ else
+ rval = codeReturn;
+
+ System.arraycopy(glyphCodes, beginGlyphIndex, rval, 0, numEntries);
+
+ return rval;
+ }
+
+ /**
+ * Returns pointers to the fonts used in this glyph vector.
+ *
+ * The array index matches that of the glyph vector itself.
+ */
+ protected long[] getGlyphFonts(int beginGlyphIndex, int numEntries,
+ long[] codeReturn)
+ {
+ long[] rval;
+
+ if( codeReturn == null || codeReturn.length < numEntries)
+ rval = new long[ numEntries ];
+ else
+ rval = codeReturn;
+
+ System.arraycopy(fontSet, beginGlyphIndex, rval, 0, numEntries);
+
+ return rval;
+ }
+
+ public Shape getGlyphLogicalBounds(int glyphIndex)
+ {
+ GlyphMetrics gm = getGlyphMetrics( glyphIndex );
+ if( gm == null )
+ return null;
+ Rectangle2D r = gm.getBounds2D();
+ Point2D p = getGlyphPosition( glyphIndex );
+
+ double[] bounds = new double[] {p.getX() + r.getX() - gm.getLSB(),
+ p.getY() + r.getY(),
+ p.getX() + r.getX() - gm.getLSB() + gm.getAdvanceX(),
+ p.getY() + r.getY() + r.getHeight()};
+
+ if (glyphTransforms[glyphIndex] != null)
+ glyphTransforms[glyphIndex].transform(bounds, 0, bounds, 0, 2);
+
+ return new Rectangle2D.Double(bounds[0], bounds[1], bounds[2] - bounds[0],
+ bounds[3] - bounds[1]);
+ }
+
+ /*
+ * FIXME: Not all glyph types are supported.
+ * (The JDK doesn't really seem to do so either)
+ */
+ public void setupGlyphMetrics()
+ {
+ metricsCache = new GlyphMetrics[ nGlyphs ];
+
+ for(int i = 0; i < nGlyphs; i++)
+ {
+ GlyphMetrics gm = (GlyphMetrics)peer.getGlyphMetrics(glyphCodes[i]);
+ if( gm == null )
+ {
+ double[] val = getMetricsNative(glyphCodes[i], fontSet[i]);
+ if( val == null )
+ gm = null;
+ else
+ {
+ gm = new GlyphMetrics(true,
+ (float)val[1],
+ (float)val[2],
+ new Rectangle2D.Double(val[3], val[4],
+ val[5], val[6] ),
+ GlyphMetrics.STANDARD );
+ peer.putGlyphMetrics( glyphCodes[ i ], gm );
+ }
+ }
+ metricsCache[ i ] = gm;
+ }
+ }
+
+ /**
+ * Returns the metrics of a single glyph.
+ */
+ public GlyphMetrics getGlyphMetrics(int glyphIndex)
+ {
+ if( metricsCache == null )
+ setupGlyphMetrics();
+
+ return metricsCache[ glyphIndex ];
+ }
+
+ /**
+ * Returns the outline of a single glyph.
+ *
+ * Despite what the Sun API says, this method returns the glyph relative to
+ * the origin of the *entire string*, not each individual glyph.
+ */
+ public Shape getGlyphOutline(int glyphIndex)
+ {
+ GeneralPath gp = getGlyphOutlineNative(glyphCodes[glyphIndex],
+ fontSet[glyphIndex]);
+
+ AffineTransform tx = AffineTransform.getTranslateInstance(glyphPositions[glyphIndex*2],
+ glyphPositions[glyphIndex*2+1]);
+ if (glyphTransforms[glyphIndex] != null)
+ tx.concatenate( glyphTransforms[glyphIndex]);
+
+ gp.transform(tx);
+ return gp;
+ }
+
+ /**
+ * Returns the position of a single glyph.
+ */
+ public Point2D getGlyphPosition(int glyphIndex)
+ {
+ return new Point2D.Float(glyphPositions[glyphIndex*2],
+ glyphPositions[glyphIndex*2 + 1]);
+ }
+
+ /**
+ * Returns the positions of multiple glyphs.
+ */
+ public float[] getGlyphPositions(int beginGlyphIndex, int numEntries,
+ float[] positionReturn)
+ {
+ if (positionReturn == null || positionReturn.length < (numEntries * 2))
+ positionReturn = new float[numEntries*2];
+
+ System.arraycopy(glyphPositions, beginGlyphIndex*2, positionReturn, 0,
+ numEntries*2);
+ return positionReturn;
+ }
+
+ /**
+ * Returns the transform of a glyph.
+ */
+ public AffineTransform getGlyphTransform(int glyphIndex)
+ {
+ return glyphTransforms[glyphIndex];
+ }
+
+ /**
+ * Checks whether any transform has been set on any glyphs.
+ */
+ protected boolean hasTransforms()
+ {
+ for (int i = 0; i < glyphTransforms.length; i++)
+ if (glyphTransforms[i] != null)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Returns the visual bounds of a glyph
+ * May be off by a pixel or two due to hinting/rasterization.
+ */
+ public Shape getGlyphVisualBounds(int glyphIndex)
+ {
+ return getGlyphOutline( glyphIndex ).getBounds2D();
+ }
+
+ /**
+ * Return the logical bounds of the whole thing.
+ */
+ public Rectangle2D getLogicalBounds()
+ {
+ if( nGlyphs == 0 )
+ return new Rectangle2D.Double(0, 0, 0, 0);
+ if( logicalBounds != null )
+ return logicalBounds;
+
+ Rectangle2D rect = (Rectangle2D)getGlyphLogicalBounds( 0 );
+ for( int i = 1; i < nGlyphs; i++ )
+ {
+ Rectangle2D r2 = (Rectangle2D)getGlyphLogicalBounds( i );
+
+ rect = rect.createUnion( r2 );
+ }
+
+ logicalBounds = rect;
+ return rect;
+ }
+
+ /**
+ * Returns the number of glyphs.
+ */
+ public int getNumGlyphs()
+ {
+ return glyphCodes.length;
+ }
+
+ /**
+ * Returns the outline of the entire GlyphVector.
+ */
+ public Shape getOutline()
+ {
+ GeneralPath path = new GeneralPath();
+ for( int i = 0; i < getNumGlyphs(); i++ )
+ path.append(getGlyphOutline(i), false);
+ return path;
+ }
+
+ /**
+ * TODO:
+ * FreeType does not currently have an API for the JSTF table. We should
+ * probably get the table ourselves from FT and pass it to some parser
+ * which the native font peers will need.
+ */
+ public GlyphJustificationInfo getGlyphJustificationInfo(int glyphIndex)
+ {
+ return null;
+ }
+
+ /**
+ * Returns the outline of the entire vector, drawn at (x,y).
+ */
+ public Shape getOutline(float x, float y)
+ {
+ AffineTransform tx = AffineTransform.getTranslateInstance( x, y );
+ GeneralPath gp = (GeneralPath)getOutline();
+ gp.transform( tx );
+ return gp;
+ }
+
+ /**
+ * Returns the visual bounds of the entire GlyphVector.
+ * May be off by a pixel or two due to hinting/rasterization.
+ */
+ public Rectangle2D getVisualBounds()
+ {
+ return getOutline().getBounds2D();
+ }
+
+ /**
+ * Sets the position of a glyph.
+ */
+ public void setGlyphPosition(int glyphIndex, Point2D newPos)
+ {
+ glyphPositions[glyphIndex*2] = (float)(newPos.getX());
+ glyphPositions[glyphIndex*2 + 1] = (float)(newPos.getY());
+ logicalBounds = null;
+ }
+
+ /**
+ * Sets the transform of a single glyph.
+ */
+ public void setGlyphTransform(int glyphIndex, AffineTransform newTX)
+ {
+ // The identity transform should never be in the glyphTransforms array;
+ // using and checking for nulls can be much faster.
+ if (newTX != null && newTX.isIdentity())
+ newTX = null;
+
+ // If the old and new transforms are identical, bail
+ if (glyphTransforms[glyphIndex] == null && newTX == null)
+ return;
+
+ if (newTX != null && newTX.equals(glyphTransforms[glyphIndex]))
+ return;
+
+ // Invalidate bounds cache and set new transform
+ logicalBounds = null;
+ glyphTransforms[glyphIndex] = newTX;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java
new file mode 100644
index 000000000..6b099063f
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java
@@ -0,0 +1,545 @@
+/* GdkFontPeer.java -- Implements FontPeer with GTK+
+ Copyright (C) 1999, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.classpath.Configuration;
+import gnu.classpath.Pointer;
+
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.font.opentype.NameDecoder;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Toolkit;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.GlyphMetrics;
+import java.awt.font.LineMetrics;
+import java.awt.font.TextLayout;
+import java.awt.geom.Rectangle2D;
+import java.text.CharacterIterator;
+import java.util.Locale;
+import java.util.Map;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+
+public class GdkFontPeer extends ClasspathFontPeer
+{
+ static final FontRenderContext DEFAULT_CTX =
+ new FontRenderContext(null, false, false);
+
+ /**
+ * Caches TextLayout instances for use in charsWidth() and drawString().
+ * The size of the cache has been chosen so that relativly large GUIs with
+ * text documents are still efficient.
+ */
+ HashMap<String,TextLayout> textLayoutCache = new GtkToolkit.LRUCache<String,TextLayout>(500);
+
+ private class GdkFontMetrics extends FontMetrics
+ {
+
+ public GdkFontMetrics (Font font)
+ {
+ super(initFont(font));
+ }
+
+ public int stringWidth (String str)
+ {
+ TextLayout tl = textLayoutCache.get(str);
+ if (tl == null)
+ {
+ tl = new TextLayout(str, font, DEFAULT_CTX);
+ textLayoutCache.put(str, tl);
+ }
+ return (int) tl.getAdvance();
+ }
+
+ public int charWidth (char ch)
+ {
+ return stringWidth (new String (new char[] { ch }));
+ }
+
+ public int charsWidth (char data[], int off, int len)
+ {
+ return stringWidth (new String (data, off, len));
+ }
+
+ public int getHeight()
+ {
+ return (int) height;
+ }
+
+ public int getLeading ()
+ {
+ return (int) (height - (ascent + descent));
+ }
+
+ public int getAscent ()
+ {
+ return (int) ascent;
+ }
+
+ public int getMaxAscent ()
+ {
+ return (int) ascent;
+ }
+
+ public int getDescent ()
+ {
+ return (int) descent;
+ }
+
+ public int getMaxDescent ()
+ {
+ return (int) maxDescent;
+ }
+
+ public int getMaxAdvance ()
+ {
+ return (int) maxAdvance;
+ }
+ }
+
+ static native void initStaticState();
+ private final int native_state = GtkGenericPeer.getUniqueInteger ();
+
+ /**
+ * Cache GlyphMetrics objects.
+ */
+ private HashMap<Integer,GlyphMetrics> metricsCache;
+
+ private static final int FONT_METRICS_ASCENT = 0;
+ private static final int FONT_METRICS_MAX_ASCENT = 1;
+ private static final int FONT_METRICS_DESCENT = 2;
+ private static final int FONT_METRICS_MAX_DESCENT = 3;
+ private static final int FONT_METRICS_MAX_ADVANCE = 4;
+ private static final int FONT_METRICS_HEIGHT = 5;
+ private static final int FONT_METRICS_UNDERLINE_OFFSET = 6;
+ private static final int FONT_METRICS_UNDERLINE_THICKNESS = 7;
+
+ float ascent;
+ float descent;
+ float maxAscent;
+ float maxDescent;
+ float maxAdvance;
+ float height;
+ float underlineOffset;
+ float underlineThickness;
+
+ GdkFontMetrics metrics;
+
+ static
+ {
+ if (true) // GCJ LOCAL
+ {
+ System.loadLibrary("gtkpeer");
+ }
+
+ initStaticState ();
+
+ }
+
+ private ByteBuffer nameTable = null;
+
+ /**
+ * The pointer to the native font data.
+ *
+ * This field is manipulated by native code. Don't change or remove
+ * without adjusting the native code.
+ */
+ private Pointer nativeFont;
+
+ private native void initState ();
+ private native void dispose ();
+ private native void setFont (String family, int style, int size);
+
+ native synchronized void getFontMetrics(double [] metrics);
+ native synchronized void getTextMetrics(String str, double [] metrics);
+
+ native void releasePeerGraphicsResource();
+
+
+ protected void finalize ()
+ {
+ releasePeerGraphicsResource();
+ dispose ();
+ }
+
+ /*
+ * Helpers for the 3-way overloading that this class seems to suffer
+ * from. Remove them if you feel like they're a performance bottleneck,
+ * for the time being I prefer my code not be written and debugged in
+ * triplicate.
+ */
+
+ private String buildString(CharacterIterator iter)
+ {
+ CPStringBuilder sb = new CPStringBuilder();
+ for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next())
+ sb.append(c);
+ return sb.toString();
+ }
+
+ private String buildString(CharacterIterator iter, int begin, int limit)
+ {
+ CPStringBuilder sb = new CPStringBuilder();
+ int i = 0;
+ for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next(), i++)
+ {
+ if (begin <= i)
+ sb.append(c);
+ if (limit <= i)
+ break;
+ }
+ return sb.toString();
+ }
+
+ private String buildString(char[] chars, int begin, int limit)
+ {
+ return new String(chars, begin, limit - begin);
+ }
+
+ /* Public API */
+
+ public GdkFontPeer (String name, int style)
+ {
+ // All fonts get a default size of 12 if size is not specified.
+ this(name, style, 12);
+ }
+
+ public GdkFontPeer (String name, int style, int size)
+ {
+ super(name, style, size);
+ initState ();
+ setFont (this.familyName, this.style, (int)this.size);
+ metricsCache = new HashMap<Integer,GlyphMetrics>();
+ setupMetrics();
+ }
+
+ public GdkFontPeer (String name, Map attributes)
+ {
+ super(name, attributes);
+ initState ();
+ setFont (this.familyName, this.style, (int)this.size);
+ metricsCache = new HashMap<Integer,GlyphMetrics>();
+ setupMetrics();
+ }
+
+
+ /**
+ * Makes sure to return a Font based on the given Font that has as
+ * peer a GdkFontPeer. Used in the initializer.
+ */
+ static Font initFont(Font font)
+ {
+ if (font == null)
+ return new Font("Dialog", Font.PLAIN, 12);
+ else if (font.getPeer() instanceof GdkFontPeer)
+ return font;
+ else
+ {
+ ClasspathToolkit toolkit;
+ toolkit = (ClasspathToolkit) Toolkit.getDefaultToolkit();
+ return toolkit.getFont(font.getName(), font.getAttributes());
+ }
+ }
+
+ private void setupMetrics()
+ {
+ double [] hires = new double[8];
+ getFontMetrics(hires);
+ ascent = (float) hires[FONT_METRICS_ASCENT];
+ maxAscent = (float) hires[FONT_METRICS_MAX_ASCENT];
+ descent = (float) hires[FONT_METRICS_DESCENT];
+ maxDescent = (float) hires[FONT_METRICS_MAX_DESCENT];
+ maxAdvance = (float) hires[FONT_METRICS_MAX_ADVANCE];
+ height = (float) hires[FONT_METRICS_HEIGHT];
+ underlineOffset = (float) hires[FONT_METRICS_UNDERLINE_OFFSET];
+ underlineThickness = (float) hires[FONT_METRICS_UNDERLINE_THICKNESS];
+ }
+
+ /**
+ * Unneeded, but implemented anyway.
+ */
+ public String getSubFamilyName(Font font, Locale locale)
+ {
+ String name;
+
+ if (locale == null)
+ locale = Locale.getDefault();
+
+ name = getName(NameDecoder.NAME_SUBFAMILY, locale);
+ if (name == null)
+ {
+ name = getName(NameDecoder.NAME_SUBFAMILY, Locale.ENGLISH);
+ if ("Regular".equals(name))
+ name = null;
+ }
+
+ return name;
+ }
+
+ /**
+ * Returns the bytes belonging to a TrueType/OpenType table,
+ * Parameters n,a,m,e identify the 4-byte ASCII tag of the table.
+ *
+ * Returns null if the font is not TT, the table is nonexistant,
+ * or if some other unexpected error occured.
+ *
+ */
+ private native byte[] getTrueTypeTable(byte n, byte a, byte m, byte e);
+
+ /**
+ * Returns the PostScript name of the font, defaults to the familyName if
+ * a PS name could not be retrieved.
+ */
+ public String getPostScriptName(Font font)
+ {
+ String name = getName(NameDecoder.NAME_POSTSCRIPT,
+ /* any language */ null);
+ if( name == null )
+ return this.familyName;
+
+ return name;
+ }
+
+ /**
+ * Extracts a String from the font&#x2019;s name table.
+ *
+ * @param name the numeric TrueType or OpenType name ID.
+ *
+ * @param locale the locale for which names shall be localized, or
+ * <code>null</code> if the locale does mot matter because the name
+ * is known to be language-independent (for example, because it is
+ * the PostScript name).
+ */
+ private String getName(int name, Locale locale)
+ {
+ if (nameTable == null)
+ {
+ byte[] data = getTrueTypeTable((byte)'n', (byte) 'a',
+ (byte) 'm', (byte) 'e');
+ if( data == null )
+ return null;
+
+ nameTable = ByteBuffer.wrap( data );
+ }
+
+ return NameDecoder.getName(nameTable, name, locale);
+ }
+
+ public boolean canDisplay (Font font, int c)
+ {
+ // FIXME: inquire with pango
+ return true;
+ }
+
+ public int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit)
+ {
+ // FIXME: inquire with pango
+ return -1;
+ }
+
+ public GlyphVector createGlyphVector (Font font,
+ FontRenderContext ctx,
+ CharacterIterator i)
+ {
+ return new FreetypeGlyphVector(font, buildString (i), ctx);
+ }
+
+ public GlyphVector createGlyphVector (Font font,
+ FontRenderContext ctx,
+ int[] glyphCodes)
+ {
+ return new FreetypeGlyphVector(font, glyphCodes, ctx);
+ }
+
+ public byte getBaselineFor (Font font, char c)
+ {
+ // FIXME: Actually check.
+ return Font.ROMAN_BASELINE;
+ }
+
+ private class GdkFontLineMetrics extends LineMetrics
+ {
+ private int nchars;
+ public GdkFontLineMetrics (GdkFontPeer fp, int n)
+ {
+ nchars = n;
+ }
+
+ public float getAscent()
+ {
+ return ascent;
+ }
+
+ public int getBaselineIndex()
+ {
+ // FIXME
+ return Font.ROMAN_BASELINE;
+ }
+
+ public float[] getBaselineOffsets()
+ {
+ return new float[3];
+ }
+
+ public float getDescent()
+ {
+ return descent;
+ }
+
+ public float getHeight()
+ {
+ return height;
+ }
+
+ public float getLeading()
+ {
+ return height - (ascent + descent);
+ }
+
+ public int getNumChars()
+ {
+ return nchars;
+ }
+
+ public float getStrikethroughOffset()
+ {
+ // FreeType doesn't seem to provide a value here.
+ return ascent / 2;
+ }
+
+ public float getStrikethroughThickness()
+ {
+ // FreeType doesn't seem to provide a value here.
+ return 1.f;
+ }
+
+ public float getUnderlineOffset()
+ {
+ return underlineOffset;
+ }
+
+ public float getUnderlineThickness()
+ {
+ return underlineThickness;
+ }
+
+ }
+
+ public LineMetrics getLineMetrics (Font font, CharacterIterator ci,
+ int begin, int limit, FontRenderContext rc)
+ {
+ return new GdkFontLineMetrics (this, limit - begin);
+ }
+
+ public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc)
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public int getMissingGlyphCode (Font font)
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public String getGlyphName (Font font, int glyphIndex)
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public int getNumGlyphs (Font font)
+ {
+ byte[] data = getTrueTypeTable((byte)'m', (byte) 'a',
+ (byte)'x', (byte) 'p');
+ if( data == null )
+ return -1;
+
+ ByteBuffer buf = ByteBuffer.wrap( data );
+ return buf.getShort(4);
+ }
+
+ public boolean hasUniformLineMetrics (Font font)
+ {
+ return true;
+ }
+
+ public GlyphVector layoutGlyphVector (Font font, FontRenderContext frc,
+ char[] chars, int start, int limit,
+ int flags)
+ {
+ return new FreetypeGlyphVector(font, chars, start, limit - start,
+ frc, flags);
+ }
+
+ public LineMetrics getLineMetrics (Font font, String str,
+ FontRenderContext frc)
+ {
+ return new GdkFontLineMetrics (this, str.length ());
+ }
+
+ public FontMetrics getFontMetrics (Font font)
+ {
+ if (metrics == null)
+ metrics = new GdkFontMetrics(font);
+ return metrics;
+ }
+
+ /**
+ * Returns a cached GlyphMetrics object for a given glyphcode,
+ * or null if it doesn't exist in the cache.
+ */
+ GlyphMetrics getGlyphMetrics( int glyphCode )
+ {
+ return metricsCache.get(new Integer(glyphCode));
+ }
+
+ /**
+ * Put a GlyphMetrics object in the cache.
+ */
+ void putGlyphMetrics( int glyphCode, GlyphMetrics metrics )
+ {
+ metricsCache.put( new Integer( glyphCode ), metrics );
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java
new file mode 100644
index 000000000..40474ff3b
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java
@@ -0,0 +1,156 @@
+/* GdkGraphicsConfiguration.java -- describes characteristics of graphics
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.BufferCapabilities;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.ImageCapabilities;
+import java.awt.Rectangle;
+import java.awt.Transparency;
+
+import java.awt.geom.AffineTransform;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.VolatileImage;
+
+public class GdkGraphicsConfiguration
+ extends GraphicsConfiguration
+{
+ GdkScreenGraphicsDevice gdkScreenGraphicsDevice;
+
+ ColorModel opaqueColorModel;
+
+ ColorModel bitmaskColorModel;
+
+ ColorModel translucentColorModel;
+
+ public GdkGraphicsConfiguration(GdkScreenGraphicsDevice dev)
+ {
+ gdkScreenGraphicsDevice = dev;
+
+ opaqueColorModel = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF, 0);
+ bitmaskColorModel = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF, 0x1000000);
+ translucentColorModel = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000);
+ }
+
+ public GraphicsDevice getDevice()
+ {
+ return gdkScreenGraphicsDevice;
+ }
+
+ public BufferedImage createCompatibleImage(int w, int h)
+ {
+ return new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ public BufferedImage createCompatibleImage(int w, int h,
+ int transparency)
+ {
+ return createCompatibleImage(w, h);
+ }
+
+ public VolatileImage createCompatibleVolatileImage(int w, int h)
+ {
+ return new GtkVolatileImage(w, h);
+ }
+
+ public VolatileImage createCompatibleVolatileImage(int w, int h,
+ ImageCapabilities caps)
+ throws java.awt.AWTException
+ {
+ return new GtkVolatileImage(w, h, caps);
+ }
+
+ public ColorModel getColorModel()
+ {
+ return opaqueColorModel;
+ }
+
+ public ColorModel getColorModel(int transparency)
+ {
+ switch (transparency)
+ {
+ case Transparency.OPAQUE:
+ return opaqueColorModel;
+ case Transparency.BITMASK:
+ return bitmaskColorModel;
+ default:
+ case Transparency.TRANSLUCENT:
+ return translucentColorModel;
+ }
+ }
+
+ public AffineTransform getDefaultTransform()
+ {
+ // FIXME: extract the GDK DPI information here.
+ return new AffineTransform();
+ }
+
+ public AffineTransform getNormalizingTransform()
+ {
+ // FIXME: extract the GDK DPI information here.
+ return new AffineTransform();
+ }
+
+ public Rectangle getBounds()
+ {
+ return gdkScreenGraphicsDevice.getBounds();
+ }
+
+ public BufferCapabilities getBufferCapabilities()
+ {
+ return new BufferCapabilities(getImageCapabilities(),
+ getImageCapabilities(),
+ BufferCapabilities.FlipContents.UNDEFINED);
+ }
+
+ public ImageCapabilities getImageCapabilities()
+ {
+ return new ImageCapabilities(false);
+ }
+
+ public VolatileImage createCompatibleVolatileImage(int width, int height, int transparency)
+ {
+ // FIXME: support the transparency argument
+ return new GtkVolatileImage(width, height);
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
new file mode 100644
index 000000000..d931f4419
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
@@ -0,0 +1,172 @@
+/* GdkGraphicsEnvironment.java -- information about the graphics environment
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.classpath.Configuration;
+import gnu.java.awt.ClasspathGraphicsEnvironment;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+import java.util.Locale;
+
+import gnu.classpath.Pointer;
+
+public class GdkGraphicsEnvironment extends ClasspathGraphicsEnvironment
+{
+ private final int native_state = GtkGenericPeer.getUniqueInteger ();
+
+ private GdkScreenGraphicsDevice defaultDevice;
+
+ private GdkScreenGraphicsDevice[] devices;
+
+ /**
+ * The pointer to the native display resource.
+ *
+ * This field is manipulated by native code. Don't change or remove
+ * without adjusting the native code.
+ */
+ private Pointer display;
+
+ static
+ {
+ if (true) // GCJ LOCAL
+ {
+ System.loadLibrary("gtkpeer");
+ }
+
+ GtkToolkit.initializeGlobalIDs();
+ initIDs();
+ }
+
+ private static native void initIDs();
+
+ public GdkGraphicsEnvironment ()
+ {
+ nativeInitState();
+ }
+
+ native void nativeInitState();
+
+ public GraphicsDevice[] getScreenDevices ()
+ {
+ if (devices == null)
+ {
+ devices = nativeGetScreenDevices();
+ }
+
+ return (GraphicsDevice[]) devices.clone();
+ }
+
+ private native GdkScreenGraphicsDevice[] nativeGetScreenDevices();
+
+ public GraphicsDevice getDefaultScreenDevice ()
+ {
+ if (GraphicsEnvironment.isHeadless ())
+ throw new HeadlessException ();
+
+ synchronized (GdkGraphicsEnvironment.class)
+ {
+ if (defaultDevice == null)
+ {
+ defaultDevice = nativeGetDefaultScreenDevice();
+ }
+ }
+
+ return defaultDevice;
+ }
+
+ private native GdkScreenGraphicsDevice nativeGetDefaultScreenDevice();
+
+ public Graphics2D createGraphics (BufferedImage image)
+ {
+ Raster raster = image.getRaster();
+ if(raster instanceof CairoSurface)
+ return ((CairoSurface)raster).getGraphics();
+
+ return new BufferedImageGraphics( image );
+ }
+
+ private native int nativeGetNumFontFamilies();
+ private native void nativeGetFontFamilies(String[] family_names);
+
+ public Font[] getAllFonts ()
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ public String[] getAvailableFontFamilyNames ()
+ {
+ String[] family_names;
+ int array_size;
+
+ array_size = nativeGetNumFontFamilies();
+ family_names = new String[array_size];
+
+ nativeGetFontFamilies(family_names);
+ return family_names;
+ }
+
+ public String[] getAvailableFontFamilyNames (Locale l)
+ {
+ throw new java.lang.UnsupportedOperationException ();
+ }
+
+ /**
+ * Used by GtkMouseInfoPeer.
+ */
+ native int[] getMouseCoordinates();
+ native boolean isWindowUnderMouse(GtkWindowPeer windowPeer);
+
+ public WritableRaster createRaster(ColorModel cm, SampleModel sm)
+ {
+ if (CairoSurface.isCompatibleSampleModel(sm)
+ && CairoSurface.isCompatibleColorModel(cm))
+ return new CairoSurface(sm.getWidth(), sm.getHeight());
+ else
+ return null;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
new file mode 100644
index 000000000..1b247c6eb
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
@@ -0,0 +1,785 @@
+/* GdkPixbufDecoder.java -- Image data decoding object
+ Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ImageConsumer;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Vector;
+
+import javax.imageio.IIOImage;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.spi.IIORegistry;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.spi.ImageWriterSpi;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.ImageOutputStream;
+
+import gnu.classpath.Configuration;
+import gnu.classpath.Pointer;
+
+public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder
+{
+ static
+ {
+ if (true) // GCJ LOCAL
+ {
+ System.loadLibrary("gtkpeer");
+ }
+
+ initStaticState ();
+ }
+
+ /**
+ * Lock that should be held for all gdkpixbuf operations. We don't use
+ * the global gdk_threads_enter/leave functions since gdkpixbuf
+ * operations can be done in parallel to drawing and manipulating gtk
+ * widgets.
+ */
+ static Object pixbufLock = new Object();
+
+ static native void initStaticState();
+ private final int native_state = GtkGenericPeer.getUniqueInteger ();
+
+ // initState() has been called, but pumpDone() has not yet been called.
+ private boolean needsClose = false;
+
+ // the current set of ImageConsumers for this decoder
+ Vector curr;
+
+ /**
+ * The pointer to the native pixbuf loader.
+ *
+ * This field is manipulated by native code. Don't change or remove
+ * without adjusting the native code.
+ */
+ private Pointer nativeDecoder;
+
+ // interface to GdkPixbuf
+ // These native functions should be called with the pixbufLock held.
+ native void initState ();
+ native void pumpBytes (byte[] bytes, int len) throws IOException;
+ native void pumpDone () throws IOException;
+ native void finish (boolean needsClose);
+
+ /**
+ * Converts given image to bytes.
+ * Will call the GdkPixbufWriter for each chunk.
+ */
+ static native void streamImage(int[] bytes, String format,
+ int width, int height,
+ boolean hasAlpha, GdkPixbufWriter writer);
+
+ // gdk-pixbuf provids data in RGBA format
+ static final ColorModel cm = new DirectColorModel (32, 0xff000000,
+ 0x00ff0000,
+ 0x0000ff00,
+ 0x000000ff);
+ public GdkPixbufDecoder (DataInput datainput)
+ {
+ super (datainput);
+ }
+
+ public GdkPixbufDecoder (InputStream in)
+ {
+ super (in);
+ }
+
+ public GdkPixbufDecoder (String filename)
+ {
+ super (filename);
+ }
+
+ public GdkPixbufDecoder (URL url)
+ {
+ super (url);
+ }
+
+ public GdkPixbufDecoder (byte[] imagedata, int imageoffset, int imagelength)
+ {
+ super (imagedata, imageoffset, imagelength);
+ }
+
+ // called back by native side: area_prepared_cb
+ void areaPrepared (int width, int height)
+ {
+
+ if (curr == null)
+ return;
+
+ for (int i = 0; i < curr.size (); i++)
+ {
+ ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
+ ic.setDimensions (width, height);
+ ic.setColorModel (cm);
+ ic.setHints (ImageConsumer.RANDOMPIXELORDER);
+ }
+ }
+
+ // called back by native side: area_updated_cb
+ void areaUpdated (int x, int y, int width, int height,
+ int pixels[], int scansize)
+ {
+ if (curr == null)
+ return;
+
+ for (int i = 0; i < curr.size (); i++)
+ {
+ ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
+ ic.setPixels (x, y, width, height, cm, pixels, 0, scansize);
+ }
+ }
+
+ // called from an async image loader of one sort or another, this method
+ // repeatedly reads bytes from the input stream and passes them through a
+ // GdkPixbufLoader using the native method pumpBytes. pumpBytes in turn
+ // decodes the image data and calls back areaPrepared and areaUpdated on
+ // this object, feeding back decoded pixel blocks, which we pass to each
+ // of the ImageConsumers in the provided Vector.
+
+ public void produce (Vector v, InputStream is) throws IOException
+ {
+ curr = v;
+
+ byte bytes[] = new byte[4096];
+ int len = 0;
+ synchronized(pixbufLock)
+ {
+ initState();
+ }
+ needsClose = true;
+
+ // Note: We don't want the pixbufLock while reading from the InputStream.
+ while ((len = is.read (bytes)) != -1)
+ {
+ synchronized(pixbufLock)
+ {
+ pumpBytes (bytes, len);
+ }
+ }
+
+ synchronized(pixbufLock)
+ {
+ pumpDone();
+ }
+
+ needsClose = false;
+
+ for (int i = 0; i < curr.size (); i++)
+ {
+ ImageConsumer ic = (ImageConsumer) curr.elementAt (i);
+ ic.imageComplete (ImageConsumer.STATICIMAGEDONE);
+ }
+
+ curr = null;
+ }
+
+ public void finalize()
+ {
+ synchronized(pixbufLock)
+ {
+ finish(needsClose);
+ }
+ }
+
+
+ public static class ImageFormatSpec
+ {
+ public String name;
+ public boolean writable = false;
+ public ArrayList<String> mimeTypes = new ArrayList<String>();
+ public ArrayList<String> extensions = new ArrayList<String>();
+
+ public ImageFormatSpec(String name, boolean writable)
+ {
+ this.name = name;
+ this.writable = writable;
+ }
+
+ public synchronized void addMimeType(String m)
+ {
+ mimeTypes.add(m);
+ }
+
+ public synchronized void addExtension(String e)
+ {
+ extensions.add(e);
+ }
+ }
+
+ static ArrayList<ImageFormatSpec> imageFormatSpecs;
+
+ public static ImageFormatSpec registerFormat(String name, boolean writable)
+ {
+ ImageFormatSpec ifs = new ImageFormatSpec(name, writable);
+ synchronized(GdkPixbufDecoder.class)
+ {
+ if (imageFormatSpecs == null)
+ imageFormatSpecs = new ArrayList<ImageFormatSpec>();
+ imageFormatSpecs.add(ifs);
+ }
+ return ifs;
+ }
+
+ static String[] getFormatNames(boolean writable)
+ {
+ ArrayList<String> names = new ArrayList<String>();
+ synchronized (imageFormatSpecs)
+ {
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
+ while (i.hasNext())
+ {
+ ImageFormatSpec ifs = i.next();
+ if (writable && !ifs.writable)
+ continue;
+ names.add(ifs.name);
+
+ /*
+ * In order to make the filtering code work, we need to register
+ * this type under every "format name" likely to be used as a synonym.
+ * This generally means "all the extensions people might use".
+ */
+
+ Iterator<String> j = ifs.extensions.iterator();
+ while (j.hasNext())
+ names.add(j.next());
+ }
+ }
+ return names.toArray(new String[names.size()]);
+ }
+
+ static String[] getFormatExtensions(boolean writable)
+ {
+ ArrayList<String> extensions = new ArrayList<String>();
+ synchronized (imageFormatSpecs)
+ {
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
+ while (i.hasNext())
+ {
+ ImageFormatSpec ifs = i.next();
+ if (writable && !ifs.writable)
+ continue;
+ Iterator<String> j = ifs.extensions.iterator();
+ while (j.hasNext())
+ extensions.add(j.next());
+ }
+ }
+ return extensions.toArray(new String[extensions.size()]);
+ }
+
+ static String[] getFormatMimeTypes(boolean writable)
+ {
+ ArrayList<String> mimeTypes = new ArrayList<String>();
+ synchronized (imageFormatSpecs)
+ {
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
+ while (i.hasNext())
+ {
+ ImageFormatSpec ifs = i.next();
+ if (writable && !ifs.writable)
+ continue;
+ Iterator<String> j = ifs.mimeTypes.iterator();
+ while (j.hasNext())
+ mimeTypes.add(j.next());
+ }
+ }
+ return mimeTypes.toArray(new String[mimeTypes.size()]);
+ }
+
+
+ static String findFormatName(Object ext, boolean needWritable)
+ {
+ if (ext == null)
+ return null;
+
+ if (!(ext instanceof String))
+ throw new IllegalArgumentException("extension is not a string");
+
+ String str = (String) ext;
+
+ Iterator<ImageFormatSpec> i = imageFormatSpecs.iterator();
+ while (i.hasNext())
+ {
+ ImageFormatSpec ifs = i.next();
+
+ if (needWritable && !ifs.writable)
+ continue;
+
+ if (ifs.name.equals(str))
+ return str;
+
+ Iterator<String> j = ifs.extensions.iterator();
+ while (j.hasNext())
+ {
+ String extension = j.next();
+ if (extension.equals(str))
+ return ifs.name;
+ }
+
+ j = ifs.mimeTypes.iterator();
+ while (j.hasNext())
+ {
+ String mimeType = j.next();
+ if (mimeType.equals(str))
+ return ifs.name;
+ }
+ }
+ throw new IllegalArgumentException("unknown extension '" + str + "'");
+ }
+
+ private static GdkPixbufReaderSpi readerSpi;
+ private static GdkPixbufWriterSpi writerSpi;
+
+ public static synchronized GdkPixbufReaderSpi getReaderSpi()
+ {
+ if (readerSpi == null)
+ readerSpi = new GdkPixbufReaderSpi();
+ return readerSpi;
+ }
+
+ public static synchronized GdkPixbufWriterSpi getWriterSpi()
+ {
+ if (writerSpi == null)
+ writerSpi = new GdkPixbufWriterSpi();
+ return writerSpi;
+ }
+
+ public static void registerSpis(IIORegistry reg)
+ {
+ reg.registerServiceProvider(getReaderSpi(), ImageReaderSpi.class);
+ reg.registerServiceProvider(getWriterSpi(), ImageWriterSpi.class);
+ }
+
+ public static class GdkPixbufWriterSpi extends ImageWriterSpi
+ {
+ public GdkPixbufWriterSpi()
+ {
+ super("GdkPixbuf", "2.x",
+ GdkPixbufDecoder.getFormatNames(true),
+ GdkPixbufDecoder.getFormatExtensions(true),
+ GdkPixbufDecoder.getFormatMimeTypes(true),
+ "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufWriter",
+ new Class[] { ImageOutputStream.class },
+ new String[] { "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufReaderSpi" },
+ false, null, null, null, null,
+ false, null, null, null, null);
+ }
+
+ public boolean canEncodeImage(ImageTypeSpecifier ts)
+ {
+ return true;
+ }
+
+ public ImageWriter createWriterInstance(Object ext)
+ {
+ return new GdkPixbufWriter(this, ext);
+ }
+
+ public String getDescription(java.util.Locale loc)
+ {
+ return "GdkPixbuf Writer SPI";
+ }
+
+ }
+
+ public static class GdkPixbufReaderSpi extends ImageReaderSpi
+ {
+ public GdkPixbufReaderSpi()
+ {
+ super("GdkPixbuf", "2.x",
+ GdkPixbufDecoder.getFormatNames(false),
+ GdkPixbufDecoder.getFormatExtensions(false),
+ GdkPixbufDecoder.getFormatMimeTypes(false),
+ "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufReader",
+ new Class[] { ImageInputStream.class },
+ new String[] { "gnu.java.awt.peer.gtk.GdkPixbufDecoder$GdkPixbufWriterSpi" },
+ false, null, null, null, null,
+ false, null, null, null, null);
+ }
+
+ public boolean canDecodeInput(Object obj)
+ {
+ return true;
+ }
+
+ public ImageReader createReaderInstance(Object ext)
+ {
+ return new GdkPixbufReader(this, ext);
+ }
+
+ public String getDescription(Locale loc)
+ {
+ return "GdkPixbuf Reader SPI";
+ }
+ }
+
+ private static class GdkPixbufWriter
+ extends ImageWriter implements Runnable
+ {
+ String ext;
+ public GdkPixbufWriter(GdkPixbufWriterSpi ownerSpi, Object ext)
+ {
+ super(ownerSpi);
+ this.ext = findFormatName(ext, true);
+ }
+
+ public IIOMetadata convertImageMetadata (IIOMetadata inData,
+ ImageTypeSpecifier imageType,
+ ImageWriteParam param)
+ {
+ return null;
+ }
+
+ public IIOMetadata convertStreamMetadata (IIOMetadata inData,
+ ImageWriteParam param)
+ {
+ return null;
+ }
+
+ public IIOMetadata getDefaultImageMetadata (ImageTypeSpecifier imageType,
+ ImageWriteParam param)
+ {
+ return null;
+ }
+
+ public IIOMetadata getDefaultStreamMetadata (ImageWriteParam param)
+ {
+ return null;
+ }
+
+ public void write (IIOMetadata streamMetadata, IIOImage i, ImageWriteParam param)
+ throws IOException
+ {
+ RenderedImage image = i.getRenderedImage();
+ Raster ras = image.getData();
+ int width = ras.getWidth();
+ int height = ras.getHeight();
+ ColorModel model = image.getColorModel();
+ int[] pixels = CairoGraphics2D.findSimpleIntegerArray (image.getColorModel(), ras);
+
+ if (pixels == null)
+ {
+ BufferedImage img;
+ if(model != null && model.hasAlpha())
+ img = CairoSurface.getBufferedImage(width, height);
+ img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ int[] pix = new int[4];
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ img.setRGB(x, y, model.getRGB(ras.getPixel(x, y, pix)));
+ pixels = CairoGraphics2D.findSimpleIntegerArray (img.getColorModel(),
+ img.getRaster());
+ model = img.getColorModel();
+ }
+
+ Thread workerThread = new Thread(this, "GdkPixbufWriter");
+ workerThread.start();
+ processImageStarted(1);
+ synchronized(pixbufLock)
+ {
+ streamImage(pixels, this.ext, width, height, model.hasAlpha(),
+ this);
+ }
+ synchronized(data)
+ {
+ data.add(DATADONE);
+ data.notifyAll();
+ }
+
+ while (workerThread.isAlive())
+ {
+ try
+ {
+ workerThread.join();
+ }
+ catch (InterruptedException ioe)
+ {
+ // Ignored.
+ }
+ }
+
+ if (exception != null)
+ throw exception;
+
+ processImageComplete();
+ }
+
+ /**
+ * Object marking end of data from native streamImage code.
+ */
+ private static final Object DATADONE = new Object();
+
+ /**
+ * Holds the data gotten from the native streamImage code.
+ * A worker thread will pull data out.
+ * Needs to be synchronized for access.
+ * The special object DATADONE is added when all data has been delivered.
+ */
+ private ArrayList<Object> data = new ArrayList<Object>();
+
+ /**
+ * Holds any IOException thrown by the run method that needs
+ * to be rethrown by the write method.
+ */
+ private IOException exception;
+
+ /** Callback for streamImage native code. **/
+ private void write(byte[] bs)
+ {
+ synchronized(data)
+ {
+ data.add(bs);
+ data.notifyAll();
+ }
+ }
+
+ public void run()
+ {
+ boolean done = false;
+ while (!done)
+ {
+ synchronized(data)
+ {
+ while (data.isEmpty())
+ {
+ try
+ {
+ data.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ /* ignore */
+ }
+ }
+
+ Object o = data.remove(0);
+ if (o == DATADONE)
+ done = true;
+ else
+ {
+ DataOutput out = (DataOutput) getOutput();
+ try
+ {
+ out.write((byte[]) o);
+ }
+ catch (IOException ioe)
+ {
+ // We are only interested in the first exception.
+ if (exception == null)
+ exception = ioe;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static class GdkPixbufReader
+ extends ImageReader
+ implements ImageConsumer
+ {
+ // ImageConsumer parts
+ GdkPixbufDecoder dec;
+ BufferedImage bufferedImage;
+ ColorModel defaultModel;
+ int width;
+ int height;
+ String ext;
+
+ public GdkPixbufReader(GdkPixbufReaderSpi ownerSpi, Object ext)
+ {
+ super(ownerSpi);
+ this.ext = findFormatName(ext, false);
+ }
+
+ public GdkPixbufReader(GdkPixbufReaderSpi ownerSpi, Object ext,
+ GdkPixbufDecoder d)
+ {
+ this(ownerSpi, ext);
+ dec = d;
+ }
+
+ public void setDimensions(int w, int h)
+ {
+ processImageStarted(1);
+ width = w;
+ height = h;
+ }
+
+ public void setProperties(Hashtable props) {}
+
+ public void setColorModel(ColorModel model)
+ {
+ defaultModel = model;
+ }
+
+ public void setHints(int flags) {}
+
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, byte[] pixels,
+ int offset, int scansize)
+ {
+ }
+
+ public void setPixels(int x, int y, int w, int h,
+ ColorModel model, int[] pixels,
+ int offset, int scansize)
+ {
+ if (model == null)
+ model = defaultModel;
+
+ if (bufferedImage == null)
+ {
+ if(model != null && model.hasAlpha())
+ bufferedImage = new BufferedImage (width, height,
+ BufferedImage.TYPE_INT_ARGB);
+ else
+ bufferedImage = new BufferedImage (width, height,
+ BufferedImage.TYPE_INT_RGB);
+ }
+
+ int pixels2[];
+ if (model != null)
+ {
+ pixels2 = new int[pixels.length];
+ for (int yy = 0; yy < h; yy++)
+ for (int xx = 0; xx < w; xx++)
+ {
+ int i = yy * scansize + xx;
+ pixels2[i] = model.getRGB (pixels[i]);
+ }
+ }
+ else
+ pixels2 = pixels;
+
+ bufferedImage.setRGB (x, y, w, h, pixels2, offset, scansize);
+ processImageProgress(y / (height == 0 ? 1 : height));
+ }
+
+ public void imageComplete(int status)
+ {
+ processImageComplete();
+ }
+
+ public BufferedImage getBufferedImage()
+ {
+ if (bufferedImage == null && dec != null)
+ dec.startProduction (this);
+ return bufferedImage;
+ }
+
+ // ImageReader parts
+
+ public int getNumImages(boolean allowSearch)
+ throws IOException
+ {
+ return 1;
+ }
+
+ public IIOMetadata getImageMetadata(int i)
+ {
+ return null;
+ }
+
+ public IIOMetadata getStreamMetadata()
+ throws IOException
+ {
+ return null;
+ }
+
+ public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex)
+ throws IOException
+ {
+ BufferedImage img = getBufferedImage();
+ Vector<ImageTypeSpecifier> vec = new Vector<ImageTypeSpecifier>();
+ vec.add(new ImageTypeSpecifier(img));
+ return vec.iterator();
+ }
+
+ public int getHeight(int imageIndex)
+ throws IOException
+ {
+ return getBufferedImage().getHeight();
+ }
+
+ public int getWidth(int imageIndex)
+ throws IOException
+ {
+ return getBufferedImage().getWidth();
+ }
+
+ public void setInput(Object input,
+ boolean seekForwardOnly,
+ boolean ignoreMetadata)
+ {
+ super.setInput(input, seekForwardOnly, ignoreMetadata);
+ Object get = getInput();
+ if (get instanceof InputStream)
+ dec = new GdkPixbufDecoder((InputStream) get);
+ else if (get instanceof DataInput)
+ dec = new GdkPixbufDecoder((DataInput) get);
+ else
+ throw new IllegalArgumentException("input object not supported: "
+ + get);
+ }
+
+ public BufferedImage read(int imageIndex, ImageReadParam param)
+ throws IOException
+ {
+ return getBufferedImage ();
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java
new file mode 100644
index 000000000..2609bad09
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkRobotPeer.java
@@ -0,0 +1,99 @@
+/* GdkRobot.java -- an XTest implementation of RobotPeer
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.AWTException;
+import java.awt.GraphicsDevice;
+import java.awt.Rectangle;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.peer.RobotPeer;
+
+/**
+ * Implements the RobotPeer interface using the XTest extension.
+ *
+ * @author Thomas Fitzsimmons
+ */
+public class GdkRobotPeer implements RobotPeer
+{
+ // gdk-pixbuf provides data in RGBA format
+ static final ColorModel cm = new DirectColorModel (32, 0xff000000,
+ 0x00ff0000,
+ 0x0000ff00,
+ 0x000000ff);
+
+ public GdkRobotPeer (GraphicsDevice screen) throws AWTException
+ {
+ // FIXME: make use of screen parameter when GraphicsDevice is
+ // implemented.
+ if (!initXTest ())
+ throw new AWTException ("XTest extension not supported");
+ }
+
+ native boolean initXTest ();
+
+ // RobotPeer methods
+ public native void mouseMove (int x, int y);
+ public native void mousePress (int buttons);
+ public native void mouseRelease (int buttons);
+ public native void mouseWheel (int wheelAmt);
+ public native void keyPress (int keycode);
+ public native void keyRelease (int keycode);
+ native int[] nativeGetRGBPixels (int x, int y, int width, int height);
+
+ public int getRGBPixel (int x, int y)
+ {
+ return cm.getRGB (nativeGetRGBPixels (x, y, 1, 1)[0]);
+ }
+
+ public int[] getRGBPixels (Rectangle r)
+ {
+ int[] gdk_pixels = nativeGetRGBPixels (r.x, r.y, r.width, r.height);
+ int[] pixels = new int[r.width * r.height];
+
+ for (int i = 0; i < r.width * r.height; i++)
+ pixels[i] = cm.getRGB (gdk_pixels[i]);
+
+ return pixels;
+ }
+
+ public void dispose()
+ {
+ // Nothing to do here yet.
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
new file mode 100644
index 000000000..1c849dfc0
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
@@ -0,0 +1,362 @@
+/* GdkScreenGraphicsDevice.java -- information about a screen device
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.DisplayMode;
+import java.awt.Frame;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.Rectangle;
+import java.awt.Window;
+import java.util.ArrayList;
+
+import gnu.classpath.Configuration;
+import gnu.classpath.Pointer;
+
+class GdkScreenGraphicsDevice extends GraphicsDevice
+{
+ private final int native_state = GtkGenericPeer.getUniqueInteger ();
+
+ private Window fullscreenWindow;
+
+ private boolean oldWindowDecorationState;
+
+ private Rectangle oldWindowBounds;
+
+ private Rectangle bounds;
+
+ private GdkGraphicsConfiguration[] configurations;
+
+ /** The <code>GdkGraphicsEnvironment</code> instance that created this
+ * <code>GdkScreenGraphicsDevice</code>. This is only needed for native
+ * methods which need to access the 'native_state' field storing a pointer
+ * to a GdkDisplay object.
+ */
+ GdkGraphicsEnvironment env;
+
+ /** An identifier that is created by Gdk
+ */
+ String idString;
+
+ /** The display modes supported by this <code>GdkScreenGraphicsDevice</code>.
+ * If the array is <code>null</code> <code>nativeGetDisplayModes</code> has
+ * to be called.
+ */
+ X11DisplayMode[] displayModes;
+
+ /** The non-changeable display mode of this <code>GdkScreenGraphicsDevice
+ * </code>. This field gets initialized by the {@link #init()} method. If it
+ * is still <code>null</code> afterwards, the XRandR extension is available
+ * and display mode changes are possible. If it is non-null XRandR is not
+ * available, no display mode changes are possible and no other native
+ * method must be called.
+ */
+ DisplayMode fixedDisplayMode;
+
+ /**
+ * The pointer to the native screen resource.
+ *
+ * This field is manipulated by native code. Don't change or remove
+ * without adjusting the native code.
+ */
+ private Pointer screen;
+
+ static
+ {
+ if (true) // GCJ LOCAL
+ {
+ System.loadLibrary("gtkpeer");
+ }
+
+ GtkToolkit.initializeGlobalIDs();
+ initIDs();
+ }
+
+ static native void initIDs();
+
+ GdkScreenGraphicsDevice (GdkGraphicsEnvironment e)
+ {
+ super();
+ env = e;
+
+ configurations = new GdkGraphicsConfiguration[1];
+ configurations[0] = new GdkGraphicsConfiguration(this);
+ }
+
+ /** This method is called from the native side immediately after
+ * the constructor is run.
+ */
+ void init()
+ {
+ fixedDisplayMode = nativeGetFixedDisplayMode(env);
+ }
+
+ /** Depending on the availability of the XRandR extension the method returns
+ * the screens' non-changeable display mode or null, meaning that XRandR can
+ * handle display mode changes.
+ */
+ native DisplayMode nativeGetFixedDisplayMode(GdkGraphicsEnvironment env);
+
+ public int getType ()
+ {
+ // Gdk manages only raster screens.
+ return GraphicsDevice.TYPE_RASTER_SCREEN;
+ }
+
+ public String getIDstring ()
+ {
+ if (idString == null)
+ idString = nativeGetIDString();
+
+ return idString;
+ }
+
+ private native String nativeGetIDString();
+
+ public GraphicsConfiguration[] getConfigurations ()
+ {
+ return (GraphicsConfiguration[]) configurations.clone();
+ }
+
+ public GraphicsConfiguration getDefaultConfiguration ()
+ {
+ return configurations[0];
+ }
+
+
+ /**
+ * Returns the current display mode of this device, or null if unknown.
+ *
+ * @return the current display mode
+ * @see #setDisplayMode(DisplayMode)
+ * @see #getDisplayModes()
+ * @since 1.4
+ */
+ public DisplayMode getDisplayMode()
+ {
+ if (fixedDisplayMode != null)
+ return fixedDisplayMode;
+
+ synchronized (this)
+ {
+ if (displayModes == null)
+ displayModes = nativeGetDisplayModes(env);
+ }
+
+ int index = nativeGetDisplayModeIndex(env);
+ int rate = nativeGetDisplayModeRate(env);
+
+ return new DisplayMode(displayModes[index].width,
+ displayModes[index].height,
+ DisplayMode.BIT_DEPTH_MULTI,
+ rate);
+ }
+
+ native int nativeGetDisplayModeIndex(GdkGraphicsEnvironment env);
+
+ native int nativeGetDisplayModeRate(GdkGraphicsEnvironment env);
+
+ public DisplayMode[] getDisplayModes()
+ {
+ if (fixedDisplayMode != null)
+ return new DisplayMode[] { fixedDisplayMode };
+
+ synchronized (this)
+ {
+ if (displayModes == null)
+ displayModes = nativeGetDisplayModes(env);
+ }
+
+ ArrayList<DisplayMode> list = new ArrayList<DisplayMode>();
+ for(int i=0;i<displayModes.length;i++)
+ for(int j=0;j<displayModes[i].rates.length;j++)
+ list.add(new DisplayMode(displayModes[i].width,
+ displayModes[i].height,
+ DisplayMode.BIT_DEPTH_MULTI,
+ displayModes[i].rates[j]));
+
+ return list.toArray(new DisplayMode[list.size()]);
+ }
+
+ native X11DisplayMode[] nativeGetDisplayModes(GdkGraphicsEnvironment env);
+
+ /**
+ * Real fullscreen exclusive mode is not supported.
+ *
+ * @return <code>false</code>
+ * @since 1.4
+ */
+ public boolean isFullScreenSupported()
+ {
+ return true;
+ }
+
+ public boolean isDisplayChangeSupported()
+ {
+ return fixedDisplayMode == null;
+ }
+
+ public void setDisplayMode(DisplayMode dm)
+ {
+ if (fixedDisplayMode != null)
+ throw new UnsupportedOperationException("Cannnot change display mode.");
+
+ if (dm == null)
+ throw new IllegalArgumentException("DisplayMode must not be null.");
+
+ synchronized (this)
+ {
+ if (displayModes == null)
+ displayModes = nativeGetDisplayModes(env);
+ }
+
+ for (int i=0; i<displayModes.length; i++)
+ if (displayModes[i].width == dm.getWidth()
+ && displayModes[i].height == dm.getHeight())
+ {
+ synchronized (this)
+ {
+ nativeSetDisplayMode(env,
+ i,
+ (short) dm.getRefreshRate());
+
+ bounds = null;
+ }
+
+ return;
+ }
+
+ throw new IllegalArgumentException("Mode not supported by this device.");
+ }
+
+ native void nativeSetDisplayMode(GdkGraphicsEnvironment env,
+ int index, short rate);
+
+ /** A class that simply encapsulates the X11 display mode data.
+ */
+ static class X11DisplayMode
+ {
+ short[] rates;
+ int width;
+ int height;
+
+ X11DisplayMode(int width, int height, short[] rates)
+ {
+ this.width = width;
+ this.height = height;
+ this.rates = rates;
+ }
+
+ }
+
+ public void setFullScreenWindow(Window w)
+ {
+ // Bring old fullscreen window back into its original state.
+ if (fullscreenWindow != null && w != fullscreenWindow)
+ {
+ if (fullscreenWindow instanceof Frame)
+ {
+ // Decoration state can only be switched when the peer is
+ // non-existent. That means we have to dispose the
+ // Frame.
+ Frame f = (Frame) fullscreenWindow;
+ if (oldWindowDecorationState != f.isUndecorated())
+ {
+ f.dispose();
+ f.setUndecorated(oldWindowDecorationState);
+ }
+ }
+
+ fullscreenWindow.setBounds(oldWindowBounds);
+
+ if (!fullscreenWindow.isVisible())
+ fullscreenWindow.setVisible(true);
+ }
+
+ // If applicable remove decoration, then maximize the window and
+ // bring it to the foreground.
+ if (w != null)
+ {
+ if (w instanceof Frame)
+ {
+ Frame f = (Frame) w;
+ oldWindowDecorationState = f.isUndecorated();
+ if (!oldWindowDecorationState)
+ {
+ f.dispose();
+ f.setUndecorated(true);
+ }
+ }
+
+ oldWindowBounds = w.getBounds();
+
+ DisplayMode dm = getDisplayMode();
+
+ w.setBounds(0, 0, dm.getWidth(), dm.getHeight());
+
+ if (!w.isVisible())
+ w.setVisible(true);
+
+ w.requestFocus();
+ w.toFront();
+
+ }
+
+ fullscreenWindow = w;
+ }
+
+ public Window getFullScreenWindow()
+ {
+ return fullscreenWindow;
+ }
+
+ Rectangle getBounds()
+ {
+ synchronized(this)
+ {
+ if (bounds == null)
+ bounds = nativeGetBounds();
+ }
+
+ return bounds;
+ }
+
+ native Rectangle nativeGetBounds();
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java
new file mode 100644
index 000000000..6ff56c0f2
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java
@@ -0,0 +1,93 @@
+/* GtkButtonPeer.java -- Implements ButtonPeer with GTK
+ Copyright (C) 1998, 1999, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Button;
+import java.awt.event.ActionEvent;
+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
+{
+ native void create (String label);
+
+ public native void connectSignals ();
+
+ /**
+ * Overridden to set Font of Label inside Button inside EventBox.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
+ native void gtkSetLabel (String label);
+ native void gtkWidgetSetForeground (int red, int green, int blue);
+ native void gtkWidgetSetBackground (int red, int green, int blue);
+ native void gtkActivate ();
+ 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);
+ }
+
+ void create ()
+ {
+ create (((Button) awtComponent).getLabel ());
+ }
+
+ public void setLabel (String label)
+ {
+ gtkSetLabel(label);
+ }
+
+ void postActionEvent (int mods)
+ {
+ q().postEvent (new ActionEvent (awtWidget,
+ ActionEvent.ACTION_PERFORMED,
+ ((Button) awtComponent).getActionCommand (),
+ mods));
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCanvasPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCanvasPeer.java
new file mode 100644
index 000000000..30c39dede
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCanvasPeer.java
@@ -0,0 +1,60 @@
+/* GtkCanvasPeer.java
+ Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Canvas;
+import java.awt.Dimension;
+import java.awt.peer.CanvasPeer;
+
+public class GtkCanvasPeer extends GtkComponentPeer implements CanvasPeer
+{
+ native void create ();
+
+ public GtkCanvasPeer (Canvas c)
+ {
+ super (c);
+ }
+
+ // Preferred size for a drawing widget is always what the user
+ // requested.
+ public Dimension preferredSize()
+ {
+ return awtComponent.getSize();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java
new file mode 100644
index 000000000..be9247e8d
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxMenuItemPeer.java
@@ -0,0 +1,74 @@
+/* GtkCheckboxMenuItemPeer.java -- Implements CheckboxMenuItemPeer with GTK+
+ Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.CheckboxMenuItem;
+import java.awt.ItemSelectable;
+import java.awt.event.ItemEvent;
+import java.awt.peer.CheckboxMenuItemPeer;
+
+public class GtkCheckboxMenuItemPeer extends GtkMenuItemPeer
+ implements CheckboxMenuItemPeer
+{
+ protected native void create (String label);
+
+ public GtkCheckboxMenuItemPeer (CheckboxMenuItem menu)
+ {
+ super (menu);
+ setState (menu.getState ());
+ }
+
+ public native void setState(boolean t);
+
+ /**
+ * Called from the signal handler of the gtk widget. Posts a
+ * ItemEvent to indicate a state changed, then calls super to post
+ * an ActionEvent.
+ */
+ protected void postMenuActionEvent ()
+ {
+ CheckboxMenuItem item = (CheckboxMenuItem)awtWidget;
+ q().postEvent (new ItemEvent ((ItemSelectable)awtWidget,
+ ItemEvent.ITEM_STATE_CHANGED,
+ item.getActionCommand(),
+ item.getState() ? ItemEvent.DESELECTED : ItemEvent.SELECTED));
+
+ super.postMenuActionEvent();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
new file mode 100644
index 000000000..6321bc64d
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java
@@ -0,0 +1,255 @@
+/* GtkCheckboxPeer.java -- Implements CheckboxPeer with GTK
+ Copyright (C) 1998, 1999, 2002, 2003, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Checkbox;
+import java.awt.CheckboxGroup;
+import java.awt.event.ItemEvent;
+import java.awt.peer.CheckboxPeer;
+import java.util.WeakHashMap;
+
+/**
+ * This class wraps either a GtkCheckButton or a GtkOptionButton
+ * depending on if this peer's owner belongs to a CheckboxGroup.
+ */
+public class GtkCheckboxPeer extends GtkComponentPeer
+ implements CheckboxPeer
+{
+ // The CheckboxGroup to which this GtkCheckboxPeer's owner belongs.
+ public CheckboxGroup current_group;
+ // The current state of the GTK checkbox.
+ private boolean currentState;
+
+ // A map from CheckboxGroup to GSList* GTK option group pointer.
+ private static WeakHashMap<CheckboxGroup,Long> groupMap
+ = new WeakHashMap<CheckboxGroup,Long>();
+
+ public native void createCheckButton ();
+ public native void createRadioButton (long groupPointer);
+
+ public native void addToGroup (long groupPointer);
+ public native void removeFromGroup ();
+ public native void switchToGroup (long groupPointer);
+
+ public native void connectSignals ();
+
+ /**
+ * Overridden to set Font of label inside button.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
+ native void gtkButtonSetLabel (String label);
+ native void gtkToggleButtonSetActive (boolean is_active);
+
+ public GtkCheckboxPeer (Checkbox c)
+ {
+ super (c);
+ }
+
+ public void create ()
+ {
+ Checkbox checkbox = (Checkbox) awtComponent;
+ current_group = checkbox.getCheckboxGroup ();
+ if (current_group == null)
+ {
+ // Initially we're not part of a group so we're backed by a
+ // GtkCheckButton.
+ createCheckButton();
+ }
+ else
+ {
+ // Initially we're part of a group.
+
+ // See if this group is already stored in our map.
+ Long groupPointer = null;
+ synchronized (groupMap)
+ {
+ groupPointer = groupMap.get(current_group);
+ }
+
+ if (groupPointer == null)
+ {
+ // We don't know about this group. Create a new native
+ // group pointer for this group and store it in our map.
+ createRadioButton(0);
+ }
+ else
+ {
+ // We already know about this group. Pass the
+ // corresponding native group pointer value to the native
+ // create method.
+ createRadioButton(groupPointer.longValue());
+ }
+ }
+ currentState = checkbox.getState();
+ gtkToggleButtonSetActive(currentState);
+
+ String label = checkbox.getLabel();
+ if (label != null)
+ gtkButtonSetLabel(label);
+ }
+
+ /**
+ * Sets native GtkCheckButton is state is different from current
+ * state. Will set currentState to state to prevent posting an
+ * event since events should only be posted for user initiated
+ * clicks on the GtkCheckButton.
+ */
+ public synchronized void setState (boolean state)
+ {
+ if (currentState != state)
+ {
+ currentState = state;
+ gtkToggleButtonSetActive(state);
+ }
+ }
+
+ public void setLabel (String label)
+ {
+ gtkButtonSetLabel (label);
+ }
+
+ public void setCheckboxGroup (CheckboxGroup group)
+ {
+ if (current_group == null && group != null)
+ {
+ // This peer's owner is currently not in a group, and now
+ // we're adding it to a group. This means that the backing
+ // GtkWidget will change from a GtkCheckButton to a
+ // GtkRadioButton.
+
+ current_group = group;
+
+ // See if the new group is already stored in our map.
+ Long groupPointer = null;
+ synchronized (groupMap)
+ {
+ groupPointer = groupMap.get(current_group);
+ }
+
+ if (groupPointer == null)
+ {
+ // We don't know about this group. Create a new native
+ // group pointer for this group and store it in our map.
+ addToGroup(0);
+ }
+ else
+ {
+ // We already know about this group. Pass the
+ // corresponding native group pointer value to the native
+ // create method.
+ addToGroup(groupPointer.longValue());
+ }
+ }
+ else if (current_group != null && group == null)
+ {
+ // This peer's owner is currently in a group, and now we're
+ // removing it from a group. This means that the backing
+ // GtkWidget will change from a GtkRadioButton to a
+ // GtkCheckButton.
+ removeFromGroup();
+ current_group = null;
+ }
+ else if (current_group == null && group == null)
+ {
+ // This peer's owner is currently not in a group, and we're
+ // not adding it to a group, so simply return.
+ return;
+ }
+ else if (current_group != group)
+ {
+ // This peer's owner is currently in a group, and now we're
+ // putting it in another group. This means that we must
+ // remove the backing GtkRadioButton from one group and add it
+ // to the other group.
+
+ current_group = group;
+
+ // See if the new group is already stored in our map.
+ Long groupPointer = null;
+ synchronized (groupMap)
+ {
+ groupPointer = groupMap.get(current_group);
+ }
+
+ if (groupPointer == null)
+ {
+ // We don't know about this group. Create a new native
+ // group pointer for this group and store it in our map.
+ switchToGroup(0);
+ }
+ else
+ {
+ // We already know about this group. Pass the
+ // corresponding native group pointer value to the native
+ // create method.
+ switchToGroup(groupPointer.longValue());
+ }
+ }
+ }
+
+ // Override the superclass postItemEvent so that the peer doesn't
+ // need information that we have.
+ // called back by native side: item_toggled_cb
+ public synchronized void postItemEvent(Object item, boolean state)
+ {
+ // Only fire event is state actually changed.
+ if (currentState != state)
+ {
+ currentState = state;
+ super.postItemEvent(awtComponent,
+ state ? ItemEvent.SELECTED : ItemEvent.DESELECTED);
+ }
+ }
+
+ public void addToGroupMap(long groupPointer)
+ {
+ synchronized (groupMap)
+ {
+ groupMap.put(current_group, new Long (groupPointer));
+ }
+ }
+
+ public void dispose ()
+ {
+ groupMap.clear();
+ current_group = null;
+ currentState = false;
+ super.dispose ();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java
new file mode 100644
index 000000000..59cacf0b6
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java
@@ -0,0 +1,142 @@
+/* GtkChoicePeer.java -- Implements ChoicePeer with GTK
+ Copyright (C) 1998, 1999, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Choice;
+import java.awt.AWTEvent;
+import java.awt.event.ItemEvent;
+import java.awt.peer.ChoicePeer;
+
+public class GtkChoicePeer extends GtkComponentPeer
+ implements ChoicePeer
+{
+ private int selected;
+
+ public GtkChoicePeer (Choice c)
+ {
+ super (c);
+
+ int count = c.getItemCount ();
+ if (count > 0)
+ {
+ for (int i = 0; i < count; i++)
+ add(c.getItem(i), i);
+
+ selected = c.getSelectedIndex();
+ if (selected >= 0)
+ select( selected );
+ }
+ else
+ selected = -1;
+ }
+
+ native void create ();
+
+ native int nativeGetSelected ();
+
+ native void connectSignals ();
+
+ native void selectNative (int position);
+
+ native void selectNativeUnlocked (int position);
+
+ public native void add (String item, int index);
+
+ native void nativeRemove(int index);
+
+ native void nativeRemoveAll();
+
+ public void select (int position)
+ {
+ if (Thread.currentThread() == GtkMainThread.mainThread)
+ selectNativeUnlocked (position);
+ else
+ selectNative (position);
+ }
+
+ public void remove( int index )
+ {
+ // Ensure the triggering of an event when removing item zero if zero is the
+ // selected item, even though the selected index doesn't change.
+ if( index == 0 && selected == 0 )
+ selected = -1;
+ nativeRemove( index );
+ }
+
+ public void removeAll()
+ {
+ selected = -1; // we do not want to trigger a select event here.
+ nativeRemoveAll();
+ }
+
+ public void addItem (String item, int position)
+ {
+ add (item, position);
+ }
+
+ /**
+ * Callback from the native side on an item-select event,
+ * which posts an event. The event is only posted if it represents an actual
+ * change. Selected is set to the peer's state initially, so that the
+ * first call to select(int) from the constructor will not trigger an event.
+ * (it should not)
+ */
+ protected void postChoiceItemEvent ( int index )
+ {
+ if( selected != index )
+ {
+ selected = index;
+ postItemEvent (((Choice) awtComponent).getItem( selected ),
+ ItemEvent.SELECTED);
+ }
+ }
+
+ /**
+ * Catches the event and calls Choice.select() if the component state
+ * needs updating.
+ */
+ public void handleEvent (AWTEvent event)
+ {
+ super.handleEvent (event);
+ if (event instanceof ItemEvent)
+ if (((ItemEvent)event).getItemSelectable() == awtComponent
+ && ((ItemEvent)event).getStateChange() == ItemEvent.SELECTED)
+ ((Choice)awtComponent).select( selected );
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java
new file mode 100644
index 000000000..4250cabaa
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java
@@ -0,0 +1,436 @@
+/* GtkClipboard.java
+ Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.Image;
+
+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.awt.datatransfer.UnsupportedFlavorException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Reader;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+
+import java.util.List;
+import java.util.Iterator;
+
+public class GtkClipboard extends Clipboard
+{
+ /**
+ * The one and only gtk+ clipboard instance for the CLIPBOARD selection.
+ */
+ final static GtkClipboard clipboard = new GtkClipboard("System Clipboard");
+
+ /**
+ * The one and only gtk+ clipboard instance for the PRIMARY selection.
+ */
+ final static GtkClipboard selection = new GtkClipboard("System Selection");
+
+ // 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
+ = DataFlavor.stringFlavor.getMimeType();
+ static final String imageMimeType
+ = DataFlavor.imageFlavor.getMimeType();
+ static final String filesMimeType
+ = DataFlavor.javaFileListFlavor.getMimeType();
+
+ // Indicates whether the results of the clipboard selection can be
+ // cached by GtkSelection. True if
+ // gdk_display_supports_selection_notification.
+ static final boolean canCache = initNativeState(clipboard, selection,
+ stringMimeType,
+ imageMimeType,
+ filesMimeType);
+
+ /**
+ * Creates the clipboard and sets the initial contents to the
+ * current gtk+ selection.
+ */
+ private GtkClipboard(String name)
+ {
+ super(name);
+ setContents(new GtkSelection(this), null);
+ }
+
+ /**
+ * Returns the one and only GtkClipboard instance for the CLIPBOARD
+ * selection.
+ */
+ static GtkClipboard getClipboardInstance()
+ {
+ return clipboard;
+ }
+
+ /**
+ * Returns the one and only GtkClipboard instance for the PRIMARY
+ * selection.
+ */
+ static GtkClipboard getSelectionInstance()
+ {
+ return selection;
+ }
+
+ /**
+ * Sets the GtkSelection facade as new contents of the clipboard.
+ * Called from gtk+ when another application grabs the clipboard and
+ * we loose ownership.
+ *
+ * @param cleared If true this is a clear event (someone takes the
+ * clipboard from us) otherwise it is an owner changed event.
+ */
+ private synchronized void setSystemContents(boolean cleared)
+ {
+ // We need to notify clipboard owner listeners when we were the
+ // owner (the selection was explictly set) and someone takes the
+ // clipboard away from us and asks us the clear any held storage,
+ // or if we weren't the owner of the clipboard to begin with, but
+ // the clipboard contents changed. We could refine this and check
+ // whether the actual available formats did in fact change, but we
+ // assume listeners will check for that anyway (and if possible we
+ // ask to cache the available formats so even if multiple
+ // listeners check after a notification the overhead should be
+ // minimal).
+ boolean owner = ! (contents instanceof GtkSelection);
+ boolean needNotification = (cleared && owner) || (! cleared && ! owner);
+ if (needNotification)
+ GtkClipboardNotifier.announce(this);
+ }
+
+ /**
+ * 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)
+ {
+ advertiseContent(null, false, false, false);
+ return;
+ }
+
+ // 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++)
+ {
+ DataFlavor flavor = flavors[i];
+ String mimeType = flavor.getMimeType();
+ mimeTargets[i] = mimeType;
+
+ if (! text)
+ if ("text".equals(flavor.getPrimaryType())
+ || flavor.isRepresentationClassReader())
+ text = true;
+
+ if (! images && flavors[i].equals(DataFlavor.imageFlavor))
+ {
+ try
+ {
+ Object o = contents.getTransferData(DataFlavor.imageFlavor);
+ if (o instanceof Image)
+ images = true;
+ }
+ catch (UnsupportedFlavorException ufe)
+ {
+ }
+ catch (IOException ioe)
+ {
+ }
+ catch (ClassCastException cce)
+ {
+ }
+ }
+
+ if (flavors[i].equals(DataFlavor.javaFileListFlavor))
+ files = true;
+ }
+
+ advertiseContent(mimeTargets, text, images, files);
+ }
+
+ /**
+ * 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()
+ {
+ 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)
+ {
+ try
+ {
+ return (String) contents.getTransferData(DataFlavor.stringFlavor);
+ }
+ catch (UnsupportedFlavorException ufe)
+ {
+ }
+ catch (IOException ioe)
+ {
+ }
+ catch (ClassCastException cce)
+ {
+ }
+ }
+
+ // Try to get a plain text reader for the current contents and
+ // turn the result into a string.
+ try
+ {
+ DataFlavor plainText = DataFlavor.getTextPlainUnicodeFlavor();
+ Reader r = plainText.getReaderForText(contents);
+ if (r != null)
+ {
+ CPStringBuilder sb = new CPStringBuilder();
+ char[] cs = new char[1024];
+ int l = r.read(cs);
+ while (l != -1)
+ {
+ sb.append(cs, 0, l);
+ l = r.read(cs);
+ }
+ return sb.toString();
+ }
+ }
+ catch (IllegalArgumentException iae)
+ {
+ }
+ catch (UnsupportedEncodingException iee)
+ {
+ }
+ catch (UnsupportedFlavorException ufe)
+ {
+ }
+ catch (IOException ioe)
+ {
+ }
+
+ return null;
+ }
+
+ /**
+ * 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
+ {
+ Object o = contents.getTransferData(DataFlavor.imageFlavor);
+ if( o instanceof GtkImage )
+ return (GtkImage) o;
+ else
+ return new GtkImage(((Image)o).getSource());
+ }
+ 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()
+ {
+ Transferable contents = this.contents;
+ if (contents == null || contents instanceof GtkSelection)
+ return null;
+
+ 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)
+ {
+ }
+
+ return null;
+ }
+
+ /**
+ * 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)
+ {
+ // 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 (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)
+ {
+ }
+ catch (IOException ioe)
+ {
+ }
+ catch (ClassCastException cce)
+ {
+ }
+
+ return null;
+ }
+
+ /**
+ * Initializes the gtk+ clipboards 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(GtkClipboard clipboard,
+ GtkClipboard selection,
+ String stringTarget,
+ String imageTarget,
+ String filesTarget);
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java
new file mode 100644
index 000000000..8e5934557
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboardNotifier.java
@@ -0,0 +1,129 @@
+/* GtkClipboardNotifier.java -- Helper for announcing GtkSelection changes.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+
+class GtkClipboardNotifier extends Thread
+{
+ /** Whether to announce a new GtkSelection has been set for CLIPBOARD. */
+ static private boolean announceClipboardChange;
+
+ /** Whether to announce a new GtkSelection has been set for PRIMARY. */
+ static private boolean announcePrimaryChange;
+
+ /**
+ * The one and only instance. All operations are synchronized on
+ * this.
+ */
+ private static GtkClipboardNotifier notifier = new GtkClipboardNotifier();
+
+ /**
+ * Creates a deamon thread that monitors this for change
+ * announcements.
+ */
+ private GtkClipboardNotifier()
+ {
+ super("GtkClipBoardNotifier");
+ setDaemon(true);
+ start();
+ }
+
+ /**
+ * Notifies that a new GtkSelection has to be announced.
+ *
+ * @param clipboard either the GtkClipboard.clipboard or the
+ * GtkClipboard.selection.
+ */
+ static void announce(GtkClipboard clipboard)
+ {
+ synchronized (notifier)
+ {
+ if (clipboard == GtkClipboard.clipboard)
+ announceClipboardChange = true;
+ else
+ announcePrimaryChange = true;
+ notifier.notifyAll();
+ }
+ }
+
+ public void run()
+ {
+ GtkClipboard clipboard;
+ while (true)
+ {
+ synchronized (this)
+ {
+ while (! announceClipboardChange && ! announcePrimaryChange)
+ {
+ try
+ {
+ this.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignore
+ }
+ }
+
+ if (announceClipboardChange)
+ {
+ clipboard = GtkClipboard.clipboard;
+ announceClipboardChange = false;
+ }
+ else
+ {
+ clipboard = GtkClipboard.selection;
+ announcePrimaryChange = false;
+ }
+ }
+
+ // Do the actual announcement without the lock held. We will
+ // notice a new change after this notification has finished.
+ try
+ {
+ clipboard.setContents(new GtkSelection(clipboard), null);
+ }
+ catch (Throwable t)
+ {
+ // should never happen, but might if we have some faulty listener.
+ t.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java
new file mode 100644
index 000000000..6e5069bc1
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java
@@ -0,0 +1,920 @@
+/* GtkComponentPeer.java -- Implements ComponentPeer with GTK
+ Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.BufferCapabilities;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.ItemSelectable;
+import java.awt.KeyboardFocusManager;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.event.FocusEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.PaintEvent;
+import java.awt.event.TextEvent;
+import java.awt.image.ColorModel;
+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.awt.peer.LightweightPeer;
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class GtkComponentPeer extends GtkGenericPeer
+ implements ComponentPeer
+{
+ VolatileImage backBuffer;
+ BufferCapabilities caps;
+
+ Component awtComponent;
+
+ Insets insets;
+
+ /**
+ * The current repaint area. Use should be guarded by synchronizing on this.
+ */
+ private Rectangle currentPaintArea;
+
+ /* 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 */
+ native boolean isEnabled ();
+ static native boolean modalHasGrab();
+
+ native int[] gtkWidgetGetForeground ();
+ native int[] gtkWidgetGetBackground ();
+ native void gtkWidgetGetDimensions (int[] dim);
+ native void gtkWidgetGetPreferredDimensions (int[] dim);
+ native void gtkWindowGetLocationOnScreen (int[] point);
+ native void gtkWindowGetLocationOnScreenUnlocked (int[] point);
+ native void gtkWidgetGetLocationOnScreen (int[] point);
+ native void gtkWidgetGetLocationOnScreenUnlocked (int[] point);
+ native void gtkWidgetSetCursor (int type, GtkImage image, int x, int y);
+ native void gtkWidgetSetCursorUnlocked (int type, GtkImage image,
+ int x, int y);
+ native void gtkWidgetSetBackground (int red, int green, int blue);
+ native void gtkWidgetSetForeground (int red, int green, int blue);
+ native void gtkWidgetSetSensitive (boolean sensitive);
+ native void gtkWidgetSetParent (ComponentPeer parent);
+ native void gtkWidgetRequestFocus ();
+ native void gtkWidgetDispatchKeyEvent (int id, long when, int mods,
+ int keyCode, int keyLocation);
+ native boolean gtkWidgetHasFocus();
+ native boolean gtkWidgetCanFocus();
+
+ native void realize();
+ native void setNativeEventMask ();
+
+ void create ()
+ {
+ throw new RuntimeException ();
+ }
+
+ native void connectSignals ();
+
+ protected GtkComponentPeer (Component awtComponent)
+ {
+ super (awtComponent);
+ this.awtComponent = awtComponent;
+ insets = new Insets (0, 0, 0, 0);
+
+ create ();
+
+ connectSignals ();
+
+ if (awtComponent.getForeground () != null)
+ setForeground (awtComponent.getForeground ());
+ if (awtComponent.getBackground () != null)
+ setBackground (awtComponent.getBackground ());
+ if (awtComponent.getFont() != null)
+ setFont(awtComponent.getFont());
+
+ Component parent = awtComponent.getParent ();
+
+ setParentAndBounds ();
+
+ setNativeEventMask ();
+
+ // This peer is guaranteed to have an X window upon construction.
+ // That is, native methods such as those in GdkGraphics can rely
+ // on this component's widget->window field being non-null.
+ realize ();
+
+ if (awtComponent.isCursorSet())
+ setCursor ();
+ }
+
+ void setParentAndBounds ()
+ {
+ setParent ();
+
+ setComponentBounds ();
+
+ setVisibleAndEnabled ();
+ }
+
+ void setParent ()
+ {
+ ComponentPeer p;
+ Component component = awtComponent;
+ do
+ {
+ component = component.getParent ();
+ p = component.getPeer ();
+ }
+ while (p instanceof java.awt.peer.LightweightPeer);
+
+ if (p != null)
+ gtkWidgetSetParent (p);
+ }
+
+ /*
+ * Set the bounds of this peer's AWT Component based on dimensions
+ * returned by the native windowing system. Most Components impose
+ * their dimensions on the peers which is what the default
+ * implementation does. However some peers, like GtkFileDialogPeer,
+ * need to pass their size back to the AWT Component.
+ */
+ void setComponentBounds ()
+ {
+ Rectangle bounds = awtComponent.getBounds ();
+ setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
+ }
+
+ void setVisibleAndEnabled ()
+ {
+ setVisible (awtComponent.isVisible ());
+ setEnabled (awtComponent.isEnabled ());
+ }
+
+ public int checkImage (Image image, int width, int height,
+ ImageObserver observer)
+ {
+ return getToolkit().checkImage(image, width, height, observer);
+ }
+
+ public Image createImage (ImageProducer producer)
+ {
+ return new GtkImage (producer);
+ }
+
+ public Image createImage (int width, int height)
+ {
+ return CairoSurface.getBufferedImage(width, height);
+ }
+
+ public void disable ()
+ {
+ setEnabled (false);
+ }
+
+ public void enable ()
+ {
+ setEnabled (true);
+ }
+
+ public ColorModel getColorModel ()
+ {
+ return ColorModel.getRGBdefault ();
+ }
+
+ public FontMetrics getFontMetrics (Font font)
+ {
+ return getToolkit().getFontMetrics(font);
+ }
+
+ // getGraphics may be overridden by derived classes but it should
+ // never return null.
+ public Graphics getGraphics ()
+ {
+ return ComponentGraphics.getComponentGraphics(this);
+ }
+
+ public Point getLocationOnScreen ()
+ {
+ int point[] = new int[2];
+ if (Thread.currentThread() == GtkMainThread.mainThread)
+ gtkWidgetGetLocationOnScreenUnlocked (point);
+ else
+ gtkWidgetGetLocationOnScreen (point);
+ return new Point (point[0], point[1]);
+ }
+
+ public Dimension getMinimumSize ()
+ {
+ return minimumSize ();
+ }
+
+ public Dimension getPreferredSize ()
+ {
+ return preferredSize ();
+ }
+
+ public Toolkit getToolkit ()
+ {
+ return Toolkit.getDefaultToolkit();
+ }
+
+ public void handleEvent (AWTEvent event)
+ {
+ int id = event.getID();
+ KeyEvent ke = null;
+
+ switch (id)
+ {
+ case PaintEvent.PAINT:
+ paintComponent((PaintEvent) event);
+ break;
+ case PaintEvent.UPDATE:
+ updateComponent((PaintEvent) event);
+ break;
+ case KeyEvent.KEY_PRESSED:
+ ke = (KeyEvent) event;
+ gtkWidgetDispatchKeyEvent (ke.getID (), ke.getWhen (), ke.getModifiersEx (),
+ ke.getKeyCode (), ke.getKeyLocation ());
+ break;
+ case KeyEvent.KEY_RELEASED:
+ ke = (KeyEvent) event;
+ gtkWidgetDispatchKeyEvent (ke.getID (), ke.getWhen (), ke.getModifiersEx (),
+ ke.getKeyCode (), ke.getKeyLocation ());
+ break;
+ }
+ }
+
+ // This method and its overrides are the only methods in the peers
+ // that should call awtComponent.paint.
+ protected void paintComponent (PaintEvent event)
+ {
+ // Do not call Component.paint if the component is not showing or
+ // if its bounds form a degenerate rectangle.
+ if (!awtComponent.isShowing()
+ || (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
+ return;
+
+ // Creating and disposing a GdkGraphics every time paint is called
+ // seems expensive. However, the graphics state does not carry
+ // over between calls to paint, and resetting the graphics object
+ // may even be more costly than simply creating a new one.
+
+ // Make sure that the paintArea includes the area from the event
+ // in the case when an application sends PaintEvents directly.
+ coalescePaintEvent(event);
+ Rectangle paintArea;
+ synchronized (this)
+ {
+ paintArea = currentPaintArea;
+ currentPaintArea = null;
+ }
+
+ if (paintArea != null)
+ {
+ Graphics g = getGraphics();
+ try
+ {
+ g.setClip(paintArea);
+ awtComponent.paint(g);
+ }
+ finally
+ {
+ g.dispose();
+ }
+ }
+ }
+
+ // This method and its overrides are the only methods in the peers
+ // that should call awtComponent.update.
+ protected void updateComponent (PaintEvent event)
+ {
+ // Do not call Component.update if the component is not showing or
+ // if its bounds form a degenerate rectangle.
+ if (!awtComponent.isShowing()
+ || (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
+ return;
+
+ // Make sure that the paintArea includes the area from the event
+ // in the case when an application sends PaintEvents directly.
+ coalescePaintEvent(event);
+ Rectangle paintArea;
+ synchronized (this)
+ {
+ paintArea = currentPaintArea;
+ currentPaintArea = null;
+ }
+
+ if (paintArea != null)
+ {
+ Graphics g = getGraphics();
+ try
+ {
+ g.setClip(paintArea);
+ awtComponent.update(g);
+ }
+ finally
+ {
+ g.dispose();
+ }
+ }
+ }
+
+ public boolean isFocusTraversable ()
+ {
+ return true;
+ }
+
+ public Dimension minimumSize ()
+ {
+ int dim[] = new int[2];
+
+ gtkWidgetGetPreferredDimensions (dim);
+
+ return new Dimension (dim[0], dim[1]);
+ }
+
+ public void paint (Graphics g)
+ {
+ }
+
+ public Dimension preferredSize ()
+ {
+ int dim[] = new int[2];
+
+ gtkWidgetGetPreferredDimensions (dim);
+
+ return new Dimension (dim[0], dim[1]);
+ }
+
+ public boolean prepareImage (Image image, int width, int height,
+ ImageObserver observer)
+ {
+ return getToolkit().prepareImage(image, width, height, observer);
+ }
+
+ public void print (Graphics g)
+ {
+ g.drawImage( ComponentGraphics.grab( this ), 0, 0, null );
+ }
+
+ public void repaint (long tm, int x, int y, int width, int height)
+ {
+ if (width < 1 || height < 1)
+ return;
+
+ if (tm <= 0)
+ q().postEvent(new PaintEvent(awtComponent, PaintEvent.UPDATE,
+ new Rectangle(x, y, width, height)));
+ else
+ RepaintTimerTask.schedule(tm, x, y, width, height, awtComponent);
+ }
+
+ /**
+ * Used for scheduling delayed paint updates on the event queue.
+ */
+ private static class RepaintTimerTask extends TimerTask
+ {
+ private static final Timer repaintTimer = new Timer(true);
+
+ private int x, y, width, height;
+ private Component awtComponent;
+
+ RepaintTimerTask(Component c, int x, int y, int width, int height)
+ {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ this.awtComponent = c;
+ }
+
+ public void run()
+ {
+ q().postEvent (new PaintEvent (awtComponent, PaintEvent.UPDATE,
+ new Rectangle (x, y, width, height)));
+ }
+
+ static void schedule(long tm, int x, int y, int width, int height,
+ Component c)
+ {
+ repaintTimer.schedule(new RepaintTimerTask(c, x, y, width, height), tm);
+ }
+ }
+
+ public void requestFocus ()
+ {
+ assert false: "Call new requestFocus() method instead";
+ }
+
+ public void reshape (int x, int y, int width, int height)
+ {
+ setBounds (x, y, width, height);
+ }
+
+ public void setBackground (Color c)
+ {
+ gtkWidgetSetBackground (c.getRed(), c.getGreen(), c.getBlue());
+ }
+
+ native void setNativeBounds (int x, int y, int width, int height);
+
+ public void setBounds (int x, int y, int width, int height)
+ {
+ int new_x = x;
+ int new_y = y;
+
+ Component parent = awtComponent.getParent ();
+
+ // Heavyweight components that are children of one or more
+ // lightweight containers have to be handled specially. Because
+ // calls to GLightweightPeer.setBounds do nothing, GTK has no
+ // knowledge of the lightweight containers' positions. So we have
+ // to add the offsets manually when placing a heavyweight
+ // component within a lightweight container. The lightweight
+ // container may itself be in a lightweight container and so on,
+ // so we need to continue adding offsets until we reach a
+ // container whose position GTK knows -- that is, the first
+ // non-lightweight.
+ Insets i;
+ while (parent.isLightweight())
+ {
+ i = ((Container) parent).getInsets();
+
+ new_x += parent.getX() + i.left;
+ new_y += parent.getY() + i.top;
+
+ parent = parent.getParent();
+ }
+ // We only need to convert from Java to GTK coordinates if we're
+ // placing a heavyweight component in a Window.
+ if (parent instanceof Window)
+ {
+ 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 ();
+
+ new_x -= insets.left;
+ new_y -= insets.top;
+ new_y += menuBarHeight;
+ }
+
+ setNativeBounds (new_x, new_y, width, height);
+
+ // If the height or width were (or are now) smaller than zero
+ // then we want to adjust the visibility.
+ setVisible(awtComponent.isVisible());
+ }
+
+ void setCursor ()
+ {
+ setCursor (awtComponent.getCursor ());
+ }
+
+ public void setCursor (Cursor cursor)
+ {
+ int x, y;
+ GtkImage image;
+ int type = cursor.getType();
+ if (cursor instanceof GtkCursor)
+ {
+ GtkCursor gtkCursor = (GtkCursor) cursor;
+ image = gtkCursor.getGtkImage();
+ Point hotspot = gtkCursor.getHotspot();
+ x = hotspot.x;
+ y = hotspot.y;
+ }
+ else
+ {
+ image = null;
+ x = 0;
+ y = 0;
+ }
+
+ if (Thread.currentThread() == GtkMainThread.mainThread)
+ gtkWidgetSetCursorUnlocked(cursor.getType(), image, x, y);
+ else
+ gtkWidgetSetCursor(cursor.getType(), image, x, y);
+ }
+
+ public void setEnabled (boolean b)
+ {
+ gtkWidgetSetSensitive (b);
+ }
+
+ public void setFont (Font f)
+ {
+ // FIXME: This should really affect the widget tree below me.
+ // Currently this is only handled if the call is made directly on
+ // a text widget, which implements setFont() itself.
+ gtkWidgetModifyFont(f.getName(), f.getStyle(), f.getSize());
+ }
+
+ public void setForeground (Color c)
+ {
+ gtkWidgetSetForeground (c.getRed(), c.getGreen(), c.getBlue());
+ }
+
+ public Color getForeground ()
+ {
+ int rgb[] = gtkWidgetGetForeground ();
+ return new Color (rgb[0], rgb[1], rgb[2]);
+ }
+
+ public Color getBackground ()
+ {
+ int rgb[] = gtkWidgetGetBackground ();
+ 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)
+ {
+ // Only really set visible when component is bigger than zero pixels.
+ if (b && ! (awtComponent instanceof Window))
+ {
+ Rectangle bounds = awtComponent.getBounds();
+ b = (bounds.width > 0) && (bounds.height > 0);
+ }
+
+ if (Thread.currentThread() == GtkMainThread.mainThread)
+ setVisibleNativeUnlocked (b);
+ else
+ setVisibleNative (b);
+ }
+
+ public void hide ()
+ {
+ setVisible (false);
+ }
+
+ public void show ()
+ {
+ setVisible (true);
+ }
+
+ protected void postMouseEvent(int id, long when, int mods, int x, int y,
+ int clickCount, boolean popupTrigger)
+ {
+ // It is important to do the getLocationOnScreen() here, instead
+ // of using the old MouseEvent constructors, because
+ // Component.getLocationOnScreen() locks on the AWT lock, which can
+ // trigger a deadlock. You don't want this.
+ Point locOnScreen = getLocationOnScreen();
+ q().postEvent(new MouseEvent(awtComponent, id, when, mods, x, y,
+ locOnScreen.x + x, locOnScreen.y + y,
+ clickCount, popupTrigger,
+ MouseEvent.NOBUTTON));
+ }
+
+ /**
+ * Callback for component_scroll_cb.
+ */
+ protected void postMouseWheelEvent(int id, long when, int mods,
+ int x, int y, int clickCount,
+ boolean popupTrigger,
+ int type, int amount, int rotation)
+ {
+ q().postEvent(new MouseWheelEvent(awtComponent, id, when, mods,
+ x, y, clickCount, popupTrigger,
+ type, amount, rotation));
+ }
+
+ protected void postExposeEvent (int x, int y, int width, int height)
+ {
+ q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
+ new Rectangle (x, y, width, height)));
+ }
+
+ protected void postKeyEvent (int id, long when, int mods,
+ int keyCode, char keyChar, int keyLocation)
+ {
+ KeyEvent keyEvent = new KeyEvent (awtComponent, id, when, mods,
+ keyCode, keyChar, keyLocation);
+
+ EventQueue q = q();
+
+ // Also post a KEY_TYPED event if keyEvent is a key press that
+ // doesn't represent an action or modifier key.
+ if (keyEvent.getID () == KeyEvent.KEY_PRESSED
+ && (!keyEvent.isActionKey ()
+ && keyCode != KeyEvent.VK_SHIFT
+ && keyCode != KeyEvent.VK_CONTROL
+ && keyCode != KeyEvent.VK_ALT))
+ {
+ synchronized(q)
+ {
+ q.postEvent(keyEvent);
+ keyEvent = new KeyEvent(awtComponent, KeyEvent.KEY_TYPED, when,
+ mods, KeyEvent.VK_UNDEFINED, keyChar,
+ keyLocation);
+ q.postEvent(keyEvent);
+ }
+ }
+ else
+ q.postEvent(keyEvent);
+ }
+
+ /**
+ * Referenced from native code.
+ *
+ * @param id
+ * @param temporary
+ */
+ protected void postFocusEvent (int id, boolean temporary)
+ {
+ q().postEvent (new FocusEvent (awtComponent, id, temporary));
+ }
+
+ protected void postItemEvent (Object item, int stateChange)
+ {
+ q().postEvent (new ItemEvent ((ItemSelectable)awtComponent,
+ ItemEvent.ITEM_STATE_CHANGED,
+ item, stateChange));
+ }
+
+ protected void postTextEvent ()
+ {
+ q().postEvent (new TextEvent (awtComponent, TextEvent.TEXT_VALUE_CHANGED));
+ }
+
+ public GraphicsConfiguration getGraphicsConfiguration ()
+ {
+ // FIXME: The component might be showing on a non-default screen.
+ GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice dev = env.getDefaultScreenDevice();
+ return dev.getDefaultConfiguration();
+ }
+
+ public void setEventMask (long mask)
+ {
+ // FIXME: just a stub for now.
+ }
+
+ public boolean isFocusable ()
+ {
+ return false;
+ }
+
+ public boolean requestFocus (Component request, boolean temporary,
+ boolean allowWindowFocus, long time)
+ {
+ assert request == awtComponent || isLightweightDescendant(request);
+ boolean retval = false;
+ if (gtkWidgetHasFocus())
+ {
+ KeyboardFocusManager kfm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ Component currentFocus = kfm.getFocusOwner();
+ if (currentFocus == request)
+ // Nothing to do in this trivial case.
+ retval = true;
+ else
+ {
+ // Requested component is a lightweight descendant of this one
+ // or the actual heavyweight.
+ // Since this (native) component is already focused, we simply
+ // change the actual focus and be done.
+ postFocusEvent(FocusEvent.FOCUS_GAINED, temporary);
+ retval = true;
+ }
+ }
+ else
+ {
+ if (gtkWidgetCanFocus())
+ {
+ if (allowWindowFocus)
+ {
+ Window window = getWindowFor(request);
+ GtkWindowPeer wPeer = (GtkWindowPeer) window.getPeer();
+ if (! wPeer.gtkWindowHasFocus())
+ wPeer.requestWindowFocus();
+ }
+ // Store requested focus component so that the corresponding
+ // event is dispatched correctly.
+ gtkWidgetRequestFocus();
+ retval = true;
+ }
+ }
+ return retval;
+ }
+
+ private Window getWindowFor(Component c)
+ {
+ Component comp = c;
+ while (! (comp instanceof Window))
+ comp = comp.getParent();
+ return (Window) comp;
+ }
+
+ /**
+ * Returns <code>true</code> if the component is a direct (== no intermediate
+ * heavyweights) lightweight descendant of this peer's component.
+ *
+ * @param c the component to check
+ *
+ * @return <code>true</code> if the component is a direct (== no intermediate
+ * heavyweights) lightweight descendant of this peer's component
+ */
+ protected boolean isLightweightDescendant(Component c)
+ {
+ Component comp = c;
+ while (comp.getPeer() instanceof LightweightPeer)
+ comp = comp.getParent();
+ return comp == awtComponent;
+ }
+
+ public boolean isObscured ()
+ {
+ return false;
+ }
+
+ public boolean canDetermineObscurity ()
+ {
+ return false;
+ }
+
+ public void coalescePaintEvent (PaintEvent e)
+ {
+ synchronized (this)
+ {
+ Rectangle newRect = e.getUpdateRect();
+ if (currentPaintArea == null)
+ currentPaintArea = newRect;
+ else
+ Rectangle.union(currentPaintArea, newRect, currentPaintArea);
+ }
+ }
+
+ public void updateCursorImmediately ()
+ {
+ if (awtComponent.getCursor() != null)
+ setCursor(awtComponent.getCursor());
+ }
+
+ public boolean handlesWheelScrolling ()
+ {
+ return false;
+ }
+
+ // Convenience method to create a new volatile image on the screen
+ // on which this component is displayed.
+ public VolatileImage createVolatileImage (int width, int height)
+ {
+ return new GtkVolatileImage (this, width, height, null);
+ }
+
+ // Creates buffers used in a buffering strategy.
+ public void createBuffers (int numBuffers, BufferCapabilities caps)
+ throws AWTException
+ {
+ // numBuffers == 2 implies double-buffering, meaning one back
+ // buffer and one front buffer.
+ if (numBuffers == 2)
+ backBuffer = new GtkVolatileImage(this, awtComponent.getWidth(),
+ awtComponent.getHeight(),
+ caps.getBackBufferCapabilities());
+ else
+ throw new AWTException("GtkComponentPeer.createBuffers:"
+ + " multi-buffering not supported");
+ this.caps = caps;
+ }
+
+ // Return the back buffer.
+ public Image getBackBuffer ()
+ {
+ return backBuffer;
+ }
+
+ // FIXME: flip should be implemented as a fast native operation
+ public void flip (BufferCapabilities.FlipContents contents)
+ {
+ getGraphics().drawImage(backBuffer,
+ awtComponent.getWidth(),
+ awtComponent.getHeight(),
+ null);
+
+ // create new back buffer and clear it to the background color.
+ if (contents == BufferCapabilities.FlipContents.BACKGROUND)
+ {
+ backBuffer = createVolatileImage(awtComponent.getWidth(),
+ awtComponent.getHeight());
+ backBuffer.getGraphics().clearRect(0, 0,
+ awtComponent.getWidth(),
+ awtComponent.getHeight());
+ }
+ // FIXME: support BufferCapabilities.FlipContents.PRIOR
+ }
+
+ // Release the resources allocated to back buffers.
+ public void destroyBuffers ()
+ {
+ 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
+
+ }
+
+ public boolean requestFocus(Component lightweightChild, boolean temporary,
+ boolean focusedWindowChangeAllowed,
+ long time, sun.awt.CausedFocusEvent.Cause cause)
+ {
+ // TODO: Implement this properly and remove the other requestFocus()
+ // methods.
+ return true;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java
new file mode 100644
index 000000000..b7eacb9f6
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java
@@ -0,0 +1,138 @@
+/* GtkContainerPeer.java -- Implements ContainerPeer with GTK
+ Copyright (C) 1998, 1999, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Font;
+import java.awt.Insets;
+import java.awt.peer.ContainerPeer;
+
+public class GtkContainerPeer extends GtkComponentPeer
+ implements ContainerPeer
+{
+ Container c;
+
+ public GtkContainerPeer(Container c)
+ {
+ super (c);
+ this.c = c;
+ }
+
+ public void beginValidate ()
+ {
+ }
+
+ public void endValidate ()
+ {
+ }
+
+ public Insets getInsets()
+ {
+ return insets;
+ }
+
+ public Insets insets()
+ {
+ return getInsets ();
+ }
+
+ public void setBounds (int x, int y, int width, int height)
+ {
+ super.setBounds (x, y, width, height);
+ }
+
+ public void setFont(Font f)
+ {
+ super.setFont(f);
+ Component[] components = ((Container) awtComponent).getComponents();
+ for (int i = 0; i < components.length; i++)
+ {
+ if (components[i].isLightweight ())
+ components[i].setFont (f);
+ else
+ {
+ GtkComponentPeer peer = (GtkComponentPeer) components[i].getPeer();
+ if (peer != null && ! peer.awtComponent.isFontSet())
+ peer.setFont(f);
+ }
+ }
+ }
+
+ public void beginLayout () { }
+ public void endLayout () { }
+ public boolean isPaintPending () { return false; }
+
+ public void setBackground (Color c)
+ {
+ super.setBackground(c);
+
+ Object components[] = ((Container) awtComponent).getComponents();
+ for (int i = 0; i < components.length; i++)
+ {
+ Component comp = (Component) components[i];
+
+ // If the child's background has not been explicitly set yet,
+ // it should inherit this container's background. This makes the
+ // child component appear as if it has a transparent background.
+ // Note that we do not alter the background property of the child,
+ // but only repaint the child with the parent's background color.
+ if (!comp.isBackgroundSet() && comp.getPeer() != null)
+ 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/GtkCursor.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCursor.java
new file mode 100644
index 000000000..e382d6331
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCursor.java
@@ -0,0 +1,72 @@
+/* GtkCursor.java -- Simple wrapper for custom cursor.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Cursor;
+import java.awt.Image;
+import java.awt.Point;
+
+/**
+ * Simple wrapper for custom Cursor.
+ */
+public class GtkCursor extends Cursor
+{
+ private final GtkImage image;
+ private final Point hotspot;
+
+ GtkCursor(Image image, Point hotspot, String name)
+ {
+ super(name);
+ if (image instanceof GtkImage)
+ this.image = (GtkImage) image;
+ else
+ this.image = new GtkImage(image.getSource());
+ this.hotspot = hotspot;
+ }
+
+ GtkImage getGtkImage()
+ {
+ return image;
+ }
+
+ Point getHotspot()
+ {
+ return hotspot;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkDialogPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkDialogPeer.java
new file mode 100644
index 000000000..3393eb9d0
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkDialogPeer.java
@@ -0,0 +1,63 @@
+/* GtkDialogPeer.java -- Implements DialogPeer with GTK
+ Copyright (C) 1998, 1999, 2002, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Dialog;
+import java.awt.peer.DialogPeer;
+
+public class GtkDialogPeer extends GtkWindowPeer
+ implements DialogPeer
+{
+ public GtkDialogPeer (Dialog dialog)
+ {
+ super (dialog);
+ }
+
+ void create ()
+ {
+ Dialog dialog = (Dialog) awtComponent;
+
+ // Create a decorated dialog window.
+ create (GDK_WINDOW_TYPE_HINT_DIALOG, !((Dialog) awtComponent).isUndecorated ());
+
+ gtkWindowSetModal (dialog.isModal ());
+ setTitle (dialog.getTitle ());
+ setResizable (dialog.isResizable ());
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkEmbeddedWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkEmbeddedWindowPeer.java
new file mode 100644
index 000000000..0533d2759
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkEmbeddedWindowPeer.java
@@ -0,0 +1,73 @@
+/* GtkEmbeddedWindowPeer.java -- Implements EmbeddedWindowPeer using a
+ GtkPlug
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.java.awt.EmbeddedWindow;
+import gnu.java.awt.peer.EmbeddedWindowPeer;
+
+public class GtkEmbeddedWindowPeer extends GtkFramePeer
+ implements EmbeddedWindowPeer
+{
+ native void create (long socket_id);
+
+ void create ()
+ {
+ create (((EmbeddedWindow) awtComponent).getHandle ());
+ }
+
+ native void construct (long socket_id);
+
+ // FIXME: embed doesn't work right now, though I believe it should.
+ // This means that you can't call setVisible (true) on an
+ // EmbeddedWindow before calling setHandle with a valid handle. The
+ // problem is that somewhere after the call to
+ // GtkEmbeddedWindow.create and before the call to
+ // GtkEmbeddedWindow.construct, the GtkPlug peer is being realized.
+ // GtkSocket silently fails to embed an already-realized GtkPlug.
+ public void embed (long handle)
+ {
+ construct (handle);
+ }
+
+ public GtkEmbeddedWindowPeer (EmbeddedWindow w)
+ {
+ super (w);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java
new file mode 100644
index 000000000..cddc530fd
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java
@@ -0,0 +1,229 @@
+/* GtkFileDialogPeer.java -- Implements FileDialogPeer with GTK
+ Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Dialog;
+import java.awt.FileDialog;
+import java.awt.event.PaintEvent;
+import java.awt.peer.FileDialogPeer;
+import java.io.File;
+import java.io.FilenameFilter;
+
+public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer
+{
+ static final String FS = System.getProperty("file.separator");
+
+ private String currentFile = null;
+ private String currentDirectory = null;
+ private FilenameFilter filter;
+
+ native void create (GtkContainerPeer parent, int mode);
+ native void connectSignals ();
+ native void nativeSetFile (String file);
+ public native String nativeGetDirectory();
+ public native void nativeSetDirectory(String directory);
+ native void nativeSetFilenameFilter (FilenameFilter filter);
+
+ public void create()
+ {
+ create((GtkContainerPeer) awtComponent.getParent().getPeer(),
+ ((FileDialog) awtComponent).getMode());
+
+ FileDialog fd = (FileDialog) awtComponent;
+
+ nativeSetDirectory(System.getProperty("user.dir"));
+ setDirectory(fd.getDirectory());
+ setFile(fd.getFile());
+
+ FilenameFilter filter = fd.getFilenameFilter();
+ if (filter != null)
+ setFilenameFilter(filter);
+ }
+
+ public GtkFileDialogPeer (FileDialog fd)
+ {
+ super (fd);
+ }
+
+ void setComponentBounds ()
+ {
+ if (awtComponent.getHeight () == 0
+ && awtComponent.getWidth () == 0)
+ {
+ int[] dims = new int[2];
+ gtkWidgetGetPreferredDimensions (dims);
+
+ if (dims[0] != awtComponent.getWidth()
+ || dims[1] != awtComponent.getHeight())
+ awtComponent.setSize(dims[0], dims[1]);
+ }
+ super.setComponentBounds ();
+ }
+
+ public void setFile (String fileName)
+ {
+ /* If nothing changed do nothing. This usually happens because
+ the only way we have to set the file name in FileDialog is by
+ calling its SetFile which will call us back. */
+ if ((fileName == null && currentFile == null)
+ || (fileName != null && fileName.equals (currentFile)))
+ return;
+
+ if (fileName == null || fileName.equals (""))
+ {
+ currentFile = "";
+ nativeSetFile ("");
+ return;
+ }
+
+ // GtkFileChooser requires absolute filenames. If the given filename
+ // is not absolute, let's construct it based on current directory.
+ currentFile = fileName;
+ if (fileName.indexOf(FS) == 0)
+ nativeSetFile(fileName);
+ else
+ nativeSetFile(nativeGetDirectory() + FS + fileName);
+ }
+
+ public void setDirectory (String directory)
+ {
+ /* If nothing changed so nothing. This usually happens because
+ the only way we have to set the directory in FileDialog is by
+ calling its setDirectory which will call us back. */
+ if ((directory == null && currentDirectory == null)
+ || (directory != null && directory.equals(currentDirectory)))
+ return;
+
+ if (directory == null || directory.equals(""))
+ {
+ currentDirectory = FS;
+ nativeSetDirectory(FS);
+ return;
+ }
+
+ // GtkFileChooser requires absolute directory names. If the given directory
+ // name is not absolute, construct it based on current directory if it is not
+ // null. Otherwise, use FS.
+ currentDirectory = directory;
+ if (directory.indexOf(FS) == 0)
+ nativeSetDirectory(directory);
+ else
+ nativeSetDirectory(nativeGetDirectory() + FS + directory);
+ }
+
+ public void setFilenameFilter (FilenameFilter filter)
+ {
+ this.filter = filter;
+ nativeSetFilenameFilter(filter);
+ }
+
+ /* This method interacts with the native callback function of the
+ same name. The native function will extract the filename from the
+ 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));
+ File dir = new File(dirname);
+ return filter.accept(dir, filename);
+ }
+
+ // Sun does not call FileDialog.update.
+ protected void updateComponent (PaintEvent event)
+ {
+ // Override GtkComponetPeer.updateComponent to do nothing.
+ }
+
+ // 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.
+ // called back by native side: handle_response_cb
+ void gtkSetFilename (String fileName)
+ {
+ FileDialog fd = (FileDialog) awtWidget;
+ if (fileName == null)
+ {
+ currentFile = null;
+ fd.setFile(null);
+ return;
+ }
+
+ int sepIndex = fileName.lastIndexOf (FS);
+ if (sepIndex < 0)
+ {
+ /* This should never happen on Unix (all paths start with '/') */
+ currentFile = fileName;
+ }
+ else
+ {
+ if (fileName.length() > (sepIndex + 1))
+ {
+ String fn = fileName.substring (sepIndex + 1);
+ currentFile = fn;
+ }
+ else
+ {
+ currentFile = null;
+ }
+
+ String dn = fileName.substring (0, sepIndex + 1);
+ currentDirectory = dn;
+ fd.setDirectory(dn);
+ }
+
+ fd.setFile (currentFile);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java
new file mode 100644
index 000000000..a36854ce0
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java
@@ -0,0 +1,254 @@
+/* GtkFramePeer.java -- Implements FramePeer with GTK
+ Copyright (C) 1999, 2002, 2004, 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Frame;
+import java.awt.Image;
+import java.awt.MenuBar;
+import java.awt.Rectangle;
+import java.awt.peer.FramePeer;
+import java.awt.peer.MenuBarPeer;
+
+public class GtkFramePeer extends GtkWindowPeer
+ implements FramePeer
+{
+ 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 ();
+ native void gtkFixedSetVisible (boolean visible);
+
+ private native void maximize();
+ private native void unmaximize();
+ private native void iconify();
+ private native void deiconify();
+
+ int getMenuBarHeight ()
+ {
+ return menuBar == null ? 0 : getMenuBarHeight (menuBar);
+ }
+
+ public void setMenuBar (MenuBar bar)
+ {
+ if (bar == null && menuBar != null)
+ {
+ // We're removing the menubar.
+ gtkFixedSetVisible (false);
+ menuBar = null;
+ removeMenuBarPeer ();
+ insets.top -= menuBarHeight;
+ menuBarHeight = 0;
+ // if component has already been validated, we need to revalidate.
+ // otherwise, it will be validated when it is shown.
+ if (awtComponent.isValid())
+ awtComponent.validate ();
+ gtkFixedSetVisible (true);
+ }
+ else if (bar != null && menuBar == null)
+ {
+ // We're adding a menubar where there was no menubar before.
+ gtkFixedSetVisible (false);
+ menuBar = (MenuBarPeer) bar.getPeer();
+ setMenuBarPeer (menuBar);
+ int menuBarWidth =
+ awtComponent.getWidth () - insets.left - insets.right;
+ if (menuBarWidth > 0)
+ setMenuBarWidth (menuBar, menuBarWidth);
+ menuBarHeight = getMenuBarHeight ();
+ insets.top += menuBarHeight;
+ // if component has already been validated, we need to revalidate.
+ // otherwise, it will be validated when it is shown.
+ if (awtComponent.isValid())
+ awtComponent.validate ();
+ gtkFixedSetVisible (true);
+ }
+ else if (bar != null && menuBar != null)
+ {
+ // We're swapping the menubar.
+ gtkFixedSetVisible (false);
+ removeMenuBarPeer();
+ int oldHeight = menuBarHeight;
+ int menuBarWidth =
+ awtComponent.getWidth () - insets.left - insets.right;
+ menuBar = (MenuBarPeer) bar.getPeer ();
+ setMenuBarPeer (menuBar);
+ if (menuBarWidth > 0)
+ setMenuBarWidth (menuBar, menuBarWidth);
+ menuBarHeight = getMenuBarHeight ();
+ if (oldHeight != menuBarHeight)
+ {
+ insets.top += (menuBarHeight - oldHeight);
+ awtComponent.validate ();
+ }
+ gtkFixedSetVisible (true);
+ }
+ }
+
+ public void setBounds (int x, int y, int width, int height)
+ {
+ int menuBarWidth = width - insets.left - insets.right;
+ if (menuBar != null && menuBarWidth > 0)
+ setMenuBarWidth (menuBar, menuBarWidth);
+
+ super.setBounds(x, y, width, height + menuBarHeight);
+ }
+
+ public void setResizable (boolean resizable)
+ {
+ // Call setSize; otherwise when resizable is changed from true to
+ // false the frame will shrink to the dimensions it had before it
+ // was resizable.
+ setSize (awtComponent.getWidth() - insets.left - insets.right,
+ awtComponent.getHeight() - insets.top - insets.bottom
+ + menuBarHeight);
+ gtkWindowSetResizable (resizable);
+ }
+
+ protected void postInsetsChangedEvent (int top, int left,
+ int bottom, int right)
+ {
+ insets.top = top + menuBarHeight;
+ insets.left = left;
+ insets.bottom = bottom;
+ insets.right = right;
+ }
+
+ public GtkFramePeer (Frame frame)
+ {
+ super (frame);
+ }
+
+ void create ()
+ {
+ // Create a normal decorated window.
+ create (GDK_WINDOW_TYPE_HINT_NORMAL,
+ !((Frame) awtComponent).isUndecorated ());
+
+ Frame frame = (Frame) awtComponent;
+
+ setMenuBar (frame.getMenuBar ());
+
+ setTitle (frame.getTitle ());
+ gtkWindowSetResizable (frame.isResizable ());
+ setIconImage(frame.getIconImage());
+ }
+
+ native void nativeSetIconImage (GtkImage image);
+
+ public void setIconImage (Image image)
+ {
+ if (image != null)
+ {
+ GtkImage gtkImage;
+ if (image instanceof GtkImage)
+ gtkImage = (GtkImage) image;
+ else
+ gtkImage = new GtkImage(image.getSource());
+
+ if (gtkImage.isLoaded && ! gtkImage.errorLoading)
+ nativeSetIconImage(gtkImage);
+ }
+ }
+
+ protected void postConfigureEvent (int x, int y, int width, int height)
+ {
+ if (menuBar != null && width > 0)
+ setMenuBarWidthUnlocked (menuBar, width);
+
+ // 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 - menuBarHeight;
+
+ // 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 + menuBarHeight;
+
+ super.postConfigureEvent(x, frame_y, width, frame_height);
+ }
+
+ public int getState ()
+ {
+ return windowState;
+ }
+
+ public void setState (int state)
+ {
+ switch (state)
+ {
+ case Frame.NORMAL:
+ if ((windowState & Frame.ICONIFIED) != 0)
+ deiconify();
+ if ((windowState & Frame.MAXIMIZED_BOTH) != 0)
+ unmaximize();
+ break;
+ case Frame.ICONIFIED:
+ iconify();
+ break;
+ case Frame.MAXIMIZED_BOTH:
+ maximize();
+ }
+ }
+
+ public void setMaximizedBounds (Rectangle r)
+ {
+
+ }
+ public void setBoundsPrivate(int x, int y, int width, int height)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean requestWindowFocus()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public Rectangle getBoundsPrivate()
+ {
+ // TODO: Implement this properly.
+ throw new InternalError("Not yet implemented");
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java
new file mode 100644
index 000000000..1b2c07b5d
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkGenericPeer.java
@@ -0,0 +1,145 @@
+/* GtkGenericPeer.java - Has a hashcode. Yuck.
+ Copyright (C) 1998, 1999, 2002, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+
+import gnu.classpath.Pointer;
+
+public class GtkGenericPeer
+{
+ // Used by Native State Association (NSA) functions to map
+ // gtk_widget to peer object.
+ final int native_state = getUniqueInteger ();
+
+ // Next native state value we will assign.
+ private static int next_native_state = 0;
+
+ // The widget or other java-side object we wrap.
+ protected final Object awtWidget;
+
+ /**
+ * The pointer to the native GTK widget.
+ *
+ * This field is manipulated by native code. Don't change or remove
+ * without adjusting the native code.
+ */
+ private Pointer widget;
+
+ /**
+ * The pointer to the global reference to this object. The native
+ * code creates a JNI global reference of the peer object to be able
+ * to pass it to the event callbacks. It gets stored here, so that
+ * we can later delete it in the dispose() method.
+ *
+ * This field is manipulated by native code. Don't change or remove
+ * without adjusting the native code.
+ */
+ private Pointer globalRef;
+
+ /**
+ * We initialize the field IDs that are used by native code here because
+ * these remain valid until a class gets unloaded.
+ */
+ static
+ {
+ GtkToolkit.initializeGlobalIDs();
+ initIDs();
+ }
+
+ /**
+ * Initializes the field IDs that are used by the native code.
+ */
+ private static native void initIDs();
+
+ /**
+ * Dispose of our native state. Calls gtk_widget_destroy on the
+ * native widget and removes the awtWidget from the native state
+ * tables. Should be overridden by subclasses if this is not (all)
+ * that needs to be done.
+ */
+ public native void dispose ();
+
+ static EventQueue q ()
+ {
+ return Toolkit.getDefaultToolkit ().getSystemEventQueue ();
+ }
+
+ protected GtkGenericPeer (Object awtWidget)
+ {
+ this.awtWidget = awtWidget;
+ }
+
+ protected void postActionEvent (String command, int mods)
+ {
+ q().postEvent (new ActionEvent (awtWidget, ActionEvent.ACTION_PERFORMED,
+ command, mods));
+ }
+
+ // Return a unique integer for use in the native state mapping
+ // code. We can't use a hash code since that is not guaranteed to
+ // be unique.
+ static synchronized int getUniqueInteger ()
+ {
+ // Let's assume this will never wrap.
+ return next_native_state++;
+ }
+
+ /**
+ * Helper method to set Font for Gtk Widget.
+ */
+ protected void gtkWidgetModifyFont(Font f)
+ {
+ gtkWidgetModifyFont(f.getName(), f.getStyle(), f.getSize());
+ }
+
+ /**
+ * Sets font for this Gtk Widget. Should be overridden by peers which
+ * are composed of different widgets or are contained in bins.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
+
+ static void printCurrentThread ()
+ {
+ System.out.println ("gtkgenericpeer, thread: " + Thread.currentThread ());
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java
new file mode 100644
index 000000000..b0a5aa0b1
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java
@@ -0,0 +1,541 @@
+/* GtkImage.java
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.MemoryImageSource;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.io.File;
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.io.ByteArrayOutputStream;
+import java.io.BufferedInputStream;
+import java.net.URL;
+import gnu.classpath.Pointer;
+
+/**
+ * GtkImage - wraps a GdkPixbuf.
+ *
+ * A GdkPixbuf is 'on-screen' and the gdk cannot draw to it,
+ * this is used for the other constructors (and other createImage methods), and
+ * corresponds to the Image implementations returned by the Toolkit.createImage
+ * methods, and is basically immutable.
+ *
+ * @author Sven de Marothy
+ */
+public class GtkImage extends Image
+{
+ int width = -1, height = -1;
+
+ /**
+ * Properties.
+ */
+ Hashtable<?,?> props;
+
+ /**
+ * Loaded or not flag, for asynchronous compatibility.
+ */
+ boolean isLoaded;
+
+ /**
+ * Pointer to the GdkPixbuf -
+ * don't change the name without changing the native code.
+ */
+ Pointer pixbuf;
+
+ /**
+ * Observer queue.
+ */
+ Vector<ImageObserver> observers;
+
+ /**
+ * Error flag for loading.
+ */
+ boolean errorLoading;
+
+ /**
+ * Original source, if created from an ImageProducer.
+ */
+ ImageProducer source;
+
+ /*
+ * The 32-bit AABBGGRR format the GDK uses.
+ */
+ static ColorModel nativeModel = new DirectColorModel(32,
+ 0x000000FF,
+ 0x0000FF00,
+ 0x00FF0000,
+ 0xFF000000);
+
+ /**
+ * The singleton GtkImage that is returned on errors by GtkToolkit.
+ */
+ private static GtkImage errorImage;
+
+ /**
+ * Lock that should be held for all gdkpixbuf operations. We don't use
+ * the global gdk_threads_enter/leave functions in most places since
+ * most gdkpixbuf operations can be done in parallel to drawing and
+ * manipulating gtk widgets.
+ */
+ static Object pixbufLock = new Object();
+
+ /**
+ * Allocate a PixBuf from a given ARGB32 buffer pointer.
+ */
+ private native void initFromBuffer( long bufferPointer );
+
+ /**
+ * Returns a copy of the pixel data as a java array.
+ * Should be called with the pixbufLock held.
+ */
+ native int[] getPixels();
+
+ /**
+ * Sets the pixel data from a java array.
+ * Should be called with the pixbufLock held.
+ */
+ private native void setPixels(int[] pixels);
+
+ /**
+ * Loads an image using gdk-pixbuf from a file.
+ * Should be called with the pixbufLock held.
+ */
+ private native boolean loadPixbuf(String name);
+
+ /**
+ * Loads an image using gdk-pixbuf from data.
+ * Should be called with the pixbufLock held.
+ */
+ private native boolean loadImageFromData(byte[] data);
+
+ /**
+ * Allocates a Gtk Pixbuf
+ * Should be called with the pixbufLock held.
+ */
+ private native void createPixbuf();
+
+ /**
+ * Frees the above.
+ * Should be called with the pixbufLock held.
+ */
+ private native void freePixbuf();
+
+ /**
+ * Sets the pixbuf to scaled copy of src image. hints are rendering hints.
+ * Should be called with the pixbufLock held.
+ */
+ private native void createScaledPixbuf(GtkImage src, int hints);
+
+ /**
+ * Constructs a GtkImage from an ImageProducer. Asynchronity is handled in
+ * the following manner:
+ * A GtkImageConsumer gets the image data, and calls setImage() when
+ * completely finished. The GtkImage is not considered loaded until the
+ * GtkImageConsumer is completely finished. We go for all "all or nothing".
+ */
+ public GtkImage (ImageProducer producer)
+ {
+ isLoaded = false;
+ observers = new Vector<ImageObserver>();
+ source = producer;
+ errorLoading = false;
+ source.startProduction(new GtkImageConsumer(this, source));
+ }
+
+ /**
+ * 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;
+ props = new Hashtable<String,Object>();
+ errorLoading = false;
+ }
+
+ /**
+ * Constructs a GtkImage by loading a given file.
+ *
+ * @throws IllegalArgumentException if the image could not be loaded.
+ */
+ public GtkImage (String filename)
+ {
+ File f = new File(filename);
+ try
+ {
+ String path = f.getCanonicalPath();
+ synchronized(pixbufLock)
+ {
+ if (loadPixbuf(f.getCanonicalPath()) != true)
+ throw new IllegalArgumentException("Couldn't load image: "
+ + filename);
+ }
+ }
+ catch(IOException e)
+ {
+ IllegalArgumentException iae;
+ iae = new IllegalArgumentException("Couldn't load image: "
+ + filename);
+ iae.initCause(e);
+ throw iae;
+ }
+
+ isLoaded = true;
+ observers = null;
+ props = new Hashtable<String,Object>();
+ }
+
+ /**
+ * Constructs a GtkImage from a byte array of an image file.
+ *
+ * @throws IllegalArgumentException if the image could not be
+ * loaded.
+ */
+ public GtkImage (byte[] data)
+ {
+ synchronized(pixbufLock)
+ {
+ if (loadImageFromData (data) != true)
+ throw new IllegalArgumentException ("Couldn't load image.");
+ }
+
+ isLoaded = true;
+ observers = null;
+ props = new Hashtable<String,Object>();
+ errorLoading = false;
+ }
+
+ /**
+ * Constructs a GtkImage from a URL. May result in an error image.
+ */
+ public GtkImage (URL url)
+ {
+ isLoaded = false;
+ observers = new Vector<ImageObserver>();
+ 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.");
+ }
+ byte[] array = baos.toByteArray();
+ synchronized(pixbufLock)
+ {
+ if (loadImageFromData(array) != true)
+ throw new IllegalArgumentException ("Couldn't load image.");
+ }
+
+ isLoaded = true;
+ observers = null;
+ props = new Hashtable<String,Object>();
+ }
+
+ /**
+ * Constructs a scaled version of the src bitmap, using the GDK.
+ */
+ private GtkImage (GtkImage src, int width, int height, int hints)
+ {
+ this.width = width;
+ this.height = height;
+ props = new Hashtable<String,Object>();
+ isLoaded = true;
+ observers = null;
+
+ // Use the GDK scaling method.
+ synchronized(pixbufLock)
+ {
+ createScaledPixbuf(src, hints);
+ }
+ }
+
+ /**
+ * Package private constructor to create a GtkImage from a given
+ * PixBuf pointer.
+ */
+ GtkImage (Pointer pixbuf)
+ {
+ this.pixbuf = pixbuf;
+ synchronized(pixbufLock)
+ {
+ createFromPixbuf();
+ }
+ isLoaded = true;
+ observers = null;
+ props = new Hashtable<String,Object>();
+ }
+
+ /**
+ * Wraps a buffer with a GtkImage.
+ *
+ * @param bufferPointer a pointer to an ARGB32 buffer
+ */
+ GtkImage(int width, int height, long bufferPointer)
+ {
+ this.width = width;
+ this.height = height;
+ props = new Hashtable<String,Object>();
+ isLoaded = true;
+ observers = null;
+ initFromBuffer( bufferPointer );
+ }
+
+ /**
+ * Returns an empty GtkImage with the errorLoading flag set.
+ * Called from GtkToolKit when some error occured, but an image needs
+ * to be returned anyway.
+ */
+ static synchronized GtkImage getErrorImage()
+ {
+ if (errorImage == null)
+ {
+ errorImage = new GtkImage();
+ errorImage.errorLoading = true;
+ }
+ return errorImage;
+ }
+
+ /**
+ * Native helper function for constructor that takes a pixbuf Pointer.
+ * Should be called with the pixbufLock held.
+ */
+ private native void createFromPixbuf();
+
+ /**
+ * Callback from the image consumer.
+ */
+ public void setImage(int width, int height,
+ int[] pixels, Hashtable<?,?> properties)
+ {
+ this.width = width;
+ this.height = height;
+ props = (properties != null) ? properties : new Hashtable<String,Object>();
+
+ if (width <= 0 || height <= 0 || pixels == null)
+ {
+ errorLoading = true;
+ return;
+ }
+
+ synchronized(pixbufLock)
+ {
+ createPixbuf();
+ setPixels(pixels);
+ }
+ isLoaded = true;
+ deliver();
+ }
+
+ // java.awt.Image methods ////////////////////////////////////////////////
+
+ public synchronized int getWidth (ImageObserver observer)
+ {
+ if (addObserver(observer))
+ return -1;
+
+ return width;
+ }
+
+ public synchronized int getHeight (ImageObserver observer)
+ {
+ if (addObserver(observer))
+ return -1;
+
+ return height;
+ }
+
+ public synchronized Object getProperty (String name, ImageObserver observer)
+ {
+ if (addObserver(observer))
+ return UndefinedProperty;
+
+ Object value = props.get (name);
+ return (value == null) ? UndefinedProperty : value;
+ }
+
+ /**
+ * Returns the source of this image.
+ */
+ public ImageProducer getSource ()
+ {
+ if (!isLoaded)
+ return null;
+
+ int[] pixels;
+ synchronized (pixbufLock)
+ {
+ if (!errorLoading)
+ pixels = getPixels();
+ else
+ return null;
+ }
+ return new MemoryImageSource(width, height, nativeModel, pixels,
+ 0, width);
+ }
+
+ /**
+ * Does nothing. Should not be called.
+ */
+ public Graphics getGraphics ()
+ {
+ throw new IllegalAccessError("This method only works for off-screen"
+ +" Images.");
+ }
+
+ /**
+ * Returns a scaled instance of this pixbuf.
+ */
+ public Image getScaledInstance(int width,
+ int height,
+ int hints)
+ {
+ if (width <= 0 || height <= 0)
+ throw new IllegalArgumentException("Width and height of scaled bitmap"
+ + "must be >= 0");
+
+ return new GtkImage(this, width, height, hints);
+ }
+
+ /**
+ * If the image is loaded and comes from an ImageProducer,
+ * regenerate the image from there.
+ *
+ * I have no idea if this is ever actually used. Since GtkImage can't be
+ * instantiated directly, how is the user to know if it was created from
+ * an ImageProducer or not?
+ */
+ public synchronized void flush ()
+ {
+ if (isLoaded && source != null)
+ {
+ observers = new Vector<ImageObserver>();
+ isLoaded = false;
+ synchronized(pixbufLock)
+ {
+ freePixbuf();
+ }
+ source.startProduction(new GtkImageConsumer(this, source));
+ }
+ }
+
+ public void finalize()
+ {
+ if (isLoaded)
+ {
+ synchronized(pixbufLock)
+ {
+ freePixbuf();
+ }
+ }
+ }
+
+ /**
+ * Returns the image status, used by GtkToolkit
+ */
+ public int checkImage (ImageObserver observer)
+ {
+ if (addObserver(observer))
+ {
+ if (errorLoading == true)
+ return ImageObserver.ERROR;
+ else
+ return 0;
+ }
+
+ return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT;
+ }
+
+
+ // Private methods ////////////////////////////////////////////////
+
+ /**
+ * Delivers notifications to all queued observers.
+ */
+ private void deliver()
+ {
+ int flags = ImageObserver.HEIGHT |
+ ImageObserver.WIDTH |
+ ImageObserver.PROPERTIES |
+ ImageObserver.ALLBITS;
+
+ if (observers != null)
+ for(int i=0; i < observers.size(); i++)
+ ((ImageObserver)observers.elementAt(i)).imageUpdate(this, flags, 0, 0,
+ width, height);
+
+ observers = null;
+ }
+
+ /**
+ * Adds an observer, if we need to.
+ * @return true if an observer was added.
+ */
+ private boolean addObserver(ImageObserver observer)
+ {
+ if (!isLoaded)
+ {
+ if(observer != null)
+ if (!observers.contains (observer))
+ observers.addElement (observer);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java
new file mode 100644
index 000000000..65cae7a89
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java
@@ -0,0 +1,169 @@
+/* GtkImageConsumer.java
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.image.ColorModel;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ImageProducer;
+import java.awt.image.MemoryImageSource;
+import java.nio.ByteOrder;
+import java.util.Hashtable;
+
+/**
+ * Helper class to GtkImage. Sits and gathers pixels for a GtkImage and then
+ * calls GtkImage.setImage().
+ *
+ * @author Sven de Marothy
+ */
+public class GtkImageConsumer implements ImageConsumer
+{
+ private GtkImage target;
+ private int width, height;
+ private Hashtable<?,?> properties;
+ private int[] pixelCache = null;
+ private ImageProducer source;
+
+ public GtkImageConsumer(GtkImage target, ImageProducer source)
+ {
+ this.target = target;
+ this.source = source;
+ }
+
+ public synchronized void imageComplete (int status)
+ {
+ // 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);
+ }
+
+ public synchronized void setColorModel (ColorModel model)
+ {
+ // This method is to inform on what the most used color model
+ // in the image is, for optimization reasons. We ignore this
+ // information.
+ }
+
+ public synchronized void setDimensions (int width, int height)
+ {
+ pixelCache = new int[width*height];
+
+ this.width = width;
+ this.height = height;
+ }
+
+ public synchronized void setHints (int flags)
+ {
+ // This method informs us in which order the pixels are
+ // delivered, for progressive-loading support, etc.
+ // Since we wait until it's all loaded, we can ignore the hints.
+ }
+
+ public synchronized void setPixels (int x, int y, int width, int height,
+ ColorModel cm, byte[] pixels,
+ int offset, int scansize)
+ {
+ setPixels (x, y, width, height, cm, convertPixels (pixels), offset,
+ scansize);
+ }
+
+ public synchronized void setPixels (int x, int y, int width, int height,
+ ColorModel cm, int[] pixels,
+ int offset, int scansize)
+ {
+ if (pixelCache == null)
+ return; // Not sure this should ever happen.
+
+ if (cm.equals(GtkImage.nativeModel))
+ for (int i = 0; i < height; i++)
+ System.arraycopy (pixels, offset + (i * scansize),
+ pixelCache, (y + i) * this.width + x,
+ width);
+ else
+ {
+ if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
+ {
+ for (int i = 0; i < height; i++)
+ for (int j = 0; j < width; j++)
+ {
+ // get in RRGGBBAA and convert to AARRGGBB
+ int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]);
+ int a = ((pix & 0xFF000000) >> 24) & 0xFF;
+ int rgb = (pix & 0x00FFFFFF) << 8;
+ pix = rgb | a;
+ pixelCache[(y + i) * this.width + x + j] = pix;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < height; i++)
+ for (int j = 0; j < width; j++)
+ {
+ // get in AARRGGBB and convert to AABBGGRR
+ int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]);
+ byte b = (byte)(pix & 0xFF);
+ byte r = (byte)(((pix & 0x00FF0000) >> 16) & 0xFF);
+ pix &= 0xFF00FF00;
+ pix |= ((b & 0xFF) << 16);
+ pix |= (r & 0xFF);
+ pixelCache[(y + i) * this.width + x + j] = pix;
+ }
+ }
+ }
+ }
+
+ /**
+ * This is an old method, no idea if it's correct.
+ */
+ private int[] convertPixels (byte[] pixels)
+ {
+ int ret[] = new int[pixels.length];
+
+ for (int i = 0; i < pixels.length; i++)
+ ret[i] = pixels[i] & 0xFF;
+
+ return ret;
+ }
+
+ public synchronized void setProperties (Hashtable<?,?> props)
+ {
+ this.properties = props;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java
new file mode 100644
index 000000000..0bdacbf33
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java
@@ -0,0 +1,102 @@
+/* GtkLabelPeer.java -- Implements LabelPeer with GTK
+ Copyright (C) 1998, 1999, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.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
+{
+ native void create (String text, float alignment);
+
+ /**
+ * Overridden to set the Font of the label inside the gtk_event_box.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
+
+ native void nativeSetAlignment (float alignment);
+
+ public native void setNativeText(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;
+ create (label.getText (), getGtkAlignment (label.getAlignment ()));
+ }
+
+ public void setText(String text)
+ {
+ if (text != null)
+ setNativeText(text);
+ }
+
+ public GtkLabelPeer (Label l)
+ {
+ super (l);
+ }
+
+ public void setAlignment (int alignment)
+ {
+ nativeSetAlignment (getGtkAlignment (alignment));
+ }
+
+ float getGtkAlignment (int alignment)
+ {
+ switch (alignment)
+ {
+ case Label.LEFT:
+ return 0.0f;
+ case Label.CENTER:
+ return 0.5f;
+ case Label.RIGHT:
+ return 1.0f;
+ }
+
+ return 0.0f;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java
new file mode 100644
index 000000000..b1cc6e522
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkListPeer.java
@@ -0,0 +1,187 @@
+/* GtkListPeer.java -- Implements ListPeer with GTK
+ Copyright (C) 1998, 1999, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.AWTEvent;
+import java.awt.Dimension;
+import java.awt.FontMetrics;
+import java.awt.List;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.ListPeer;
+
+public class GtkListPeer extends GtkComponentPeer
+ implements ListPeer
+{
+ void create ()
+ {
+ List list = (List) awtComponent;
+
+ create (list.getRows ());
+
+ setMultipleMode (list.isMultipleMode ());
+ }
+
+ native void create (int rows);
+ native void connectSignals ();
+
+ /**
+ * Overridden to set the Font of the text insode the gtk_scrolled_window.
+ */
+ protected native void gtkWidgetModifyFont (String name, int style, int size);
+
+ native void gtkWidgetRequestFocus ();
+
+ native void getSize (int rows, int visibleRows, int dims[]);
+
+ public GtkListPeer (List list)
+ {
+ super (list);
+
+ setMultipleMode (list.isMultipleMode ());
+
+ if (list.getItemCount () > 0)
+ append (list.getItems ());
+ }
+
+ native void append (String items[]);
+
+ public native void add (String item, int index);
+
+ public void addItem (String item, int index)
+ {
+ add (item, index);
+ }
+
+ public void clear ()
+ {
+ removeAll ();
+ }
+
+ public native void delItems (int start, int end);
+ public native void deselect (int index);
+
+ public Dimension getMinimumSize (int rows)
+ {
+ return minimumSize (rows);
+ }
+
+ public Dimension getPreferredSize (int rows)
+ {
+ return preferredSize (rows);
+ }
+
+ public native int[] getSelectedIndexes ();
+ public native void makeVisible (int index);
+
+ public Dimension minimumSize (int rows)
+ {
+ int dims[] = new int[2];
+
+ int visibleRows = ((List) awtComponent).getRows();
+ getSize (rows, visibleRows, dims);
+ return new Dimension (dims[0], dims[1]);
+ }
+
+ public Dimension preferredSize (int rows)
+ {
+ // getSize returns the minimum size of the list.
+ // The width is too narrow for a typical list.
+ List l = (List) awtComponent;
+ Dimension d = getMinimumSize();
+ FontMetrics fm = l.getFontMetrics(l.getFont());
+ return new Dimension(d.width + fm.stringWidth("1234567890"), d.height);
+ }
+
+ public void removeAll ()
+ {
+ delItems (0, -1);
+ }
+
+ public native void select (int index);
+ public native void setMultipleMode (boolean b);
+
+ public void setMultipleSelections (boolean b)
+ {
+ setMultipleMode (b);
+ }
+
+ public void handleEvent (AWTEvent e)
+ {
+ if (e.getID () == MouseEvent.MOUSE_CLICKED && isEnabled ())
+ {
+ // Only generate the ActionEvent on the second click of a
+ // multiple click.
+ MouseEvent me = (MouseEvent) e;
+ if (!me.isConsumed ()
+ && (me.getModifiersEx () & MouseEvent.BUTTON1_DOWN_MASK) != 0
+ && me.getClickCount() == 2)
+ {
+ String selectedItem = ((List) awtComponent).getSelectedItem ();
+
+ // Double-click only generates an Action event if
+ // something is selected.
+ if (selectedItem != null)
+ postActionEvent (((List) awtComponent).getSelectedItem (),
+ me.getModifiersEx ());
+ }
+ }
+
+ if (e.getID () == KeyEvent.KEY_PRESSED)
+ {
+ KeyEvent ke = (KeyEvent) e;
+ if (!ke.isConsumed () && ke.getKeyCode () == KeyEvent.VK_ENTER)
+ {
+ String selectedItem = ((List) awtComponent).getSelectedItem ();
+
+ // Enter only generates an Action event if something is
+ // selected.
+ if (selectedItem != null)
+ postActionEvent (selectedItem, ke.getModifiersEx ());
+ }
+ }
+
+ super.handleEvent (e);
+ }
+
+ protected void postItemEvent (int item, int stateChange)
+ {
+ postItemEvent (new Integer (item), stateChange);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMainThread.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMainThread.java
new file mode 100644
index 000000000..0ee61df84
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMainThread.java
@@ -0,0 +1,188 @@
+/* GtkMainThread.java -- Wrapper for the GTK main thread, and some utilities.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.java.awt.peer.NativeEventLoopRunningEvent;
+
+/**
+ * The Java thread representing the native GTK main loop, that is,
+ * GtkMainThread.mainThread, terminates when GtkToolkit.gtkMain()
+ * returns. That happens in response to the last window peer being
+ * disposed (see GtkWindowPeer.dispose).
+ *
+ * When GtkMainThread.destroyWindow is called for the last window, it
+ * in turn calls GtkMainThread.endMainThread, which calls gtk_quit.
+ * gtk_quit signals gtk_main to return, which causes GtkMainThread.run
+ * to return.
+ *
+ * There should only be one native GTK main loop running at any given
+ * time. In order to safely start and stop the GTK main loop, we use
+ * a running flag and corresponding runningLock. startMainThread will
+ * not return until the native GTK main loop has started, as confirmed
+ * by the native set_running_flag callback setting the running flag to
+ * true. Without this protection, gtk_quit could be called before the
+ * main loop has actually started, which causes GTK assertion
+ * failures. Likewise endMainThread will not return until the native
+ * GTK main loop has ended.
+ *
+ * post_running_flag_callback is called during gtk_main initialization
+ * and no window can be created before startMainThread returns. This
+ * ensures that calling post_running_flag_callback is the first action
+ * taken by the native GTK main loop.
+ *
+ * GtkMainThread.mainThread is started when the window count goes from
+ * zero to one.
+ *
+ * GtkMainThread keeps the AWT event queue informed of its status by
+ * posting NativeEventLoopRunningEvents. The AWT event queue uses
+ * this status to determine whether or not the AWT exit conditions
+ * have been met (see EventQueue.isShutdown).
+ */
+public class GtkMainThread extends Thread
+{
+ /** Count of the number of open windows */
+ private static int numberOfWindows = 0;
+
+ /** Lock for the above */
+ private static Object nWindowsLock = new Object();
+
+ /** Indicates whether or not the GTK main loop is running. */
+ private static boolean running = false;
+
+ /** Lock for the above. */
+ private static Object runningLock = new Object();
+
+ /** The main thread instance (singleton) */
+ public static GtkMainThread mainThread;
+
+ /** Constructs a main thread */
+ private GtkMainThread()
+ {
+ super("GTK main thread");
+ }
+
+ public void run ()
+ {
+ GtkToolkit.gtkMain ();
+ }
+
+ private static void setRunning(boolean running)
+ {
+ synchronized (runningLock)
+ {
+ GtkMainThread.running = running;
+ runningLock.notifyAll();
+ }
+ }
+
+ private static void startMainThread()
+ {
+ synchronized (runningLock)
+ {
+ if (!running)
+ {
+ mainThread = new GtkMainThread();
+ mainThread.start();
+
+ while (!running)
+ {
+ try
+ {
+ runningLock.wait();
+ }
+ catch (InterruptedException e)
+ {
+ System.err.println ("GtkMainThread.startMainThread:"
+ + " interrupted while waiting "
+ + " for GTK main loop to start");
+ }
+ }
+ GtkGenericPeer.q()
+ .postEvent(new NativeEventLoopRunningEvent(Boolean.TRUE));
+ }
+ }
+ }
+
+ private static void endMainThread()
+ {
+ synchronized (runningLock)
+ {
+ if (running)
+ {
+ GtkToolkit.gtkQuit();
+
+ while (running)
+ {
+ try
+ {
+ runningLock.wait();
+ }
+ catch (InterruptedException e)
+ {
+ System.err.println ("GtkMainThread.endMainThread:"
+ + " interrupted while waiting "
+ + " for GTK main loop to stop");
+ }
+ }
+ GtkGenericPeer.q()
+ .postEvent(new NativeEventLoopRunningEvent(Boolean.FALSE));
+ }
+ }
+ }
+
+ public static void createWindow()
+ {
+ synchronized (nWindowsLock)
+ {
+ if (numberOfWindows == 0)
+ startMainThread();
+ numberOfWindows++;
+ }
+ }
+
+ public static void destroyWindow()
+ {
+ synchronized (nWindowsLock)
+ {
+ numberOfWindows--;
+ if (numberOfWindows == 0)
+ endMainThread();
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
new file mode 100644
index 000000000..c3427b18f
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java
@@ -0,0 +1,113 @@
+/* GtkMenuBarPeer.java -- Implements MenuBarPeer with GTK+
+ Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.peer.MenuBarPeer;
+
+public class GtkMenuBarPeer extends GtkMenuComponentPeer
+ implements MenuBarPeer
+{
+ /** Whether we already have an help menu set on this peer. */
+ private boolean hasHelpMenu;
+
+ /**
+ * Creates the gtk+ widget for this peer and puts it in the nsa
+ * table. Called from the (super class) constructor.
+ */
+ protected native void create();
+
+ /**
+ * Adds a new GtkMenuPeer to the end of the GtkMenuBarPeer.
+ */
+ private native void addMenu(GtkMenuPeer menu);
+
+ /**
+ * Creates a new GtkMenuBarPeer associated with the given MenuBar.
+ */
+ public GtkMenuBarPeer(MenuBar menubar)
+ {
+ super(menubar);
+ }
+
+ /**
+ * Adds a help menu to this MenuBar. Gnome styleguides say the help
+ * menu is just the last item in the menubar (they are NOT right
+ * justified).
+ */
+ public void addHelpMenu (Menu menu)
+ {
+ if (hasHelpMenu)
+ {
+ // Remove the (help) menu, which is after all the other items.
+ delMenu(((MenuBar) awtWidget).getMenuCount());
+ hasHelpMenu = false;
+ }
+
+ if (menu != null)
+ {
+ addMenu(menu);
+ hasHelpMenu = true;
+ }
+ }
+
+ /**
+ * Deletes the menu at (zero-based) index from this GtkMenuBar.
+ */
+ public native void delMenu(int index);
+
+ /**
+ * Adds the GtkMenuPeer associated with the Menu to this
+ * GtkMenuBarPeer. Makes sure that any help menus keep the last menu
+ * on the bar.
+ */
+ public void addMenu(Menu m)
+ {
+ // Make sure the help menu is the last one.
+ if (hasHelpMenu)
+ {
+ addHelpMenu(null);
+ addMenu((GtkMenuPeer) m.getPeer());
+ addHelpMenu(((MenuBar) awtWidget).getHelpMenu());
+ }
+ else
+ addMenu((GtkMenuPeer) m.getPeer());
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java
new file mode 100644
index 000000000..78f640361
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java
@@ -0,0 +1,104 @@
+/* GtkMenuComponentPeer.java -- Implements MenuComponentPeer with GTK+
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Font;
+import java.awt.MenuComponent;
+import java.awt.MenuContainer;
+import java.awt.peer.MenuComponentPeer;
+
+public abstract class GtkMenuComponentPeer extends GtkGenericPeer
+ implements MenuComponentPeer
+{
+ /**
+ * Creates the associated gtk+ widget and stores it in the nsa table
+ * for this peer. Called by the constructor.
+ */
+ protected abstract void create ();
+
+ /**
+ * Sets font based on MenuComponent font, or containing menu(bar)
+ * parent font.
+ */
+ private void setFont()
+ {
+ MenuComponent mc = ((MenuComponent) awtWidget);
+ Font f = mc.getFont();
+
+ if (f == null)
+ {
+ MenuContainer parent = mc.getParent ();
+ // Submenus inherit the font of their containing Menu(Bar).
+ if (parent instanceof MenuComponent)
+ f = parent.getFont ();
+ }
+
+ setFont(f);
+ }
+
+ /**
+ * Will call the abstract <code>create()</code> that needs to be
+ * overridden by subclasses, to create the MenuComponent. It will
+ * then correctly setup the font for the component based on the
+ * component and/or its containing parent component.
+ */
+ public GtkMenuComponentPeer(MenuComponent component)
+ {
+ super(component);
+ create();
+ setFont();
+ }
+
+ /**
+ * Removes the awtWidget components from the native state tables.
+ * Subclasses should call <code>super.dispose()</code> if they don't
+ * remove these themselves.
+ */
+ public native void dispose();
+
+ /**
+ * Sets the font for this particular MenuComponent only (not any
+ * containing items, if any).
+ */
+ public void setFont(Font font)
+ {
+ if (font != null)
+ gtkWidgetModifyFont(font);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java
new file mode 100644
index 000000000..ea523e953
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuItemPeer.java
@@ -0,0 +1,116 @@
+/* GtkMenuItemPeer.java -- Implements MenuItemPeer with GTK+
+ Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.MenuItem;
+import java.awt.peer.MenuItemPeer;
+
+public class GtkMenuItemPeer extends GtkMenuComponentPeer
+ implements MenuItemPeer
+{
+ /**
+ * Creates the associated gtk+ widget and stores it in the nsa table
+ * for this peer. Called by the create() method with the label name
+ * of the associated MenuItem. Needs to be overridden my subclasses
+ * that want to create a different gtk+ widget.
+ */
+ protected native void create (String label);
+
+ /**
+ * Called from constructor to enable signals from an item. If a
+ * subclass needs different (or no) signals connected this method
+ * should be overridden.
+ */
+ protected native void connectSignals ();
+
+ /**
+ * Overridden to set font on menu item label.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
+
+ /**
+ * Creates the associated gtk+ widget and stores it in the nsa table
+ * for this peer. Called by the (super class) constructor.
+ * Overridden to get the label if the assiociated MenuItem and to
+ * call create(String).
+ */
+ protected void create()
+ {
+ create (((MenuItem) awtWidget).getLabel());
+ }
+
+ /**
+ * Creates a new GtkMenuItemPeer associated with the given MenuItem.
+ * It will call create(), setFont(), setEnabled() and
+ * connectSignals() in that order.
+ */
+ public GtkMenuItemPeer(MenuItem item)
+ {
+ super(item);
+ setEnabled (item.isEnabled());
+ connectSignals();
+ }
+
+ /**
+ * Calls setEnabled(false).
+ */
+ public void disable()
+ {
+ setEnabled(false);
+ }
+
+ /**
+ * Calls setEnabled(true).
+ */
+ public void enable()
+ {
+ setEnabled(true);
+ }
+
+ public native void setEnabled(boolean b);
+ public native void setLabel(String label);
+
+ /**
+ * Callback setup through connectSignals().
+ */
+ protected void postMenuActionEvent ()
+ {
+ postActionEvent (((MenuItem)awtWidget).getActionCommand (), 0);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java
new file mode 100644
index 000000000..c55347393
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java
@@ -0,0 +1,126 @@
+/* GtkMenuPeer.java -- Implements MenuPeer with GTK+
+ Copyright (C) 1999, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Component;
+import java.awt.Menu;
+import java.awt.MenuContainer;
+import java.awt.MenuItem;
+import java.awt.MenuShortcut;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+
+public class GtkMenuPeer extends GtkMenuItemPeer
+ implements MenuPeer
+{
+ /**
+ * Creates the associated gtk+ widget and stores it in the nsa table
+ * for this peer. Called by the create() method with the label name
+ * of the associated MenuItem. Overridden to greate a Menu widget.
+ */
+ protected native void create (String label);
+
+ private native void addItem(MenuItemPeer item, int key,
+ boolean shiftModifier);
+
+ /** XXX - Document this and the override in GtkPopupMenuPeer. */
+ native void setupAccelGroup (GtkGenericPeer container);
+
+ private native void addTearOff ();
+
+ /**
+ * Overridden to not connect any signals.
+ */
+ protected void connectSignals()
+ {
+ // No signals to connect.
+ }
+
+ public GtkMenuPeer (Menu menu)
+ {
+ super (menu);
+
+ if (menu.isTearOff())
+ addTearOff();
+
+ MenuContainer parent = menu.getParent ();
+ if (parent instanceof Menu)
+ setupAccelGroup ((GtkMenuPeer)((Menu)parent).getPeer ());
+ else if (parent instanceof Component)
+ setupAccelGroup ((GtkComponentPeer)((Component)parent).getPeer ());
+ else
+ setupAccelGroup (null); // XXX, should we warn about unknown parent?
+ }
+
+ public void addItem (MenuItem item)
+ {
+ int key = 0;
+ boolean shiftModifier = false;
+
+ MenuShortcut ms = item.getShortcut ();
+ if (ms != null)
+ {
+ key = ms.getKey ();
+ shiftModifier = ms.usesShiftModifier ();
+ }
+
+ addItem ((MenuItemPeer) item.getPeer (), key, shiftModifier);
+ }
+
+ public void addItem (MenuItemPeer item, MenuShortcut ms)
+ {
+ int key = 0;
+ boolean shiftModifier = false;
+
+ if (ms != null)
+ {
+ key = ms.getKey ();
+ shiftModifier = ms.usesShiftModifier ();
+ }
+
+ addItem (item, key, shiftModifier);
+ }
+
+ public native void delItem(int index);
+
+ public void addSeparator()
+ {
+ // FIXME: implement
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java
new file mode 100644
index 000000000..55c9146c4
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMouseInfoPeer.java
@@ -0,0 +1,65 @@
+/* GtkToolkit.java -- Implements an AWT Toolkit using GTK for peers
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Point;
+import java.awt.GraphicsDevice;
+import java.awt.Window;
+import java.awt.peer.MouseInfoPeer;
+
+/**
+ * The MouseInfoPeer is so small, I'm including it here.
+ */
+public class GtkMouseInfoPeer implements MouseInfoPeer
+{
+ private static GdkGraphicsEnvironment gde = new GdkGraphicsEnvironment();
+
+ public int fillPointWithCoords(Point p)
+ {
+ int[] coords = gde.getMouseCoordinates();
+ p.x = coords[1];
+ p.y = coords[2];
+ return coords[0];
+ }
+
+ public boolean isWindowUnderMouse(Window w)
+ {
+ return gde.isWindowUnderMouse((GtkWindowPeer) w.getPeer());
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java
new file mode 100644
index 000000000..00b506c10
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPanelPeer.java
@@ -0,0 +1,67 @@
+/* GtkPanelPeer.java -- Implements PanelPeer with GTK
+ Copyright (C) 1998, 1999, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.AWTEvent;
+import java.awt.Panel;
+import java.awt.event.MouseEvent;
+import java.awt.peer.PanelPeer;
+
+public class GtkPanelPeer extends GtkContainerPeer
+ implements PanelPeer
+{
+ native void create ();
+
+ public GtkPanelPeer (Panel p)
+ {
+ super (p);
+ }
+
+ public void handleEvent(AWTEvent event)
+ {
+ int id = event.getID();
+
+ if (id == MouseEvent.MOUSE_PRESSED)
+ awtComponent.requestFocusInWindow();
+
+ super.handleEvent(event);
+ }
+
+ native void connectSignals ();
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java
new file mode 100644
index 000000000..1b0ec8e63
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkPopupMenuPeer.java
@@ -0,0 +1,68 @@
+/* GtkPopupMenuPeer.java -- Implements PopupMenuPeer with GTK+
+ Copyright (C) 1999, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Component;
+import java.awt.Event;
+import java.awt.Point;
+import java.awt.PopupMenu;
+import java.awt.peer.PopupMenuPeer;
+
+public class GtkPopupMenuPeer extends GtkMenuPeer
+ implements PopupMenuPeer
+{
+ public GtkPopupMenuPeer (PopupMenu menu)
+ {
+ super (menu);
+ }
+
+ native void setupAccelGroup (GtkGenericPeer container);
+
+ native void show (int x, int y, long time);
+ public void show (Component origin, int x, int y)
+ {
+ Point abs = origin.getLocationOnScreen ();
+ show (abs.x + x, abs.y + y, 0);
+ }
+
+ public void show (Event e)
+ {
+
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java
new file mode 100644
index 000000000..657a27608
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollPanePeer.java
@@ -0,0 +1,111 @@
+/* GtkScrollPanePeer.java -- Implements ScrollPanePeer with GTK
+ Copyright (C) 1998, 1999, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Adjustable;
+import java.awt.Dimension;
+import java.awt.ScrollPane;
+import java.awt.peer.ScrollPanePeer;
+
+public class GtkScrollPanePeer extends GtkContainerPeer
+ implements ScrollPanePeer
+{
+ native void create (int width, int height);
+
+ void create ()
+ {
+ create (awtComponent.getWidth (), awtComponent.getHeight ());
+ }
+
+ // native void gtkScrolledWindowSetScrollPosition(int x, int y);
+ native void gtkScrolledWindowSetHScrollIncrement (int u);
+ native void gtkScrolledWindowSetVScrollIncrement (int u);
+
+ public GtkScrollPanePeer (ScrollPane sp)
+ {
+ super (sp);
+
+ setPolicy (sp.getScrollbarDisplayPolicy ());
+ }
+
+ native void setPolicy (int policy);
+ public void childResized (int width, int height)
+ {
+ int dim[] = new int[2];
+
+ gtkWidgetGetDimensions (dim);
+
+ // If the child is in this range, GTK adds both scrollbars, but
+ // the AWT doesn't. So set the peer's scroll policy to
+ // GTK_POLICY_NEVER.
+ if ((width > dim[0] - getVScrollbarWidth () && width <= dim[0])
+ && (height > dim[1] - getHScrollbarHeight () && height <= dim[1]))
+ setPolicy (ScrollPane.SCROLLBARS_NEVER);
+ else
+ setPolicy (((ScrollPane) awtComponent).getScrollbarDisplayPolicy ());
+ }
+
+ public native int getHScrollbarHeight();
+ public native int getVScrollbarWidth();
+ public native void setScrollPosition(int x, int y);
+
+ public Dimension getPreferredSize ()
+ {
+ return awtComponent.getSize();
+ }
+
+ public void setUnitIncrement (Adjustable adj, int u)
+ {
+ if (adj.getOrientation()==Adjustable.HORIZONTAL)
+ gtkScrolledWindowSetHScrollIncrement (u);
+ else
+ gtkScrolledWindowSetVScrollIncrement (u);
+ }
+
+ public void setValue (Adjustable adj, int v)
+ {
+// System.out.println("SPP: setVal: "+adj+":"+v);
+// Point p=myScrollPane.getScrollPosition ();
+// if (adj.getOrientation()==Adjustable.HORIZONTAL)
+// gtkScrolledWindowSetScrollPosition (v,p.y);
+// else
+// gtkScrolledWindowSetScrollPosition (p.x,v);
+// adj.setValue(v);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
new file mode 100644
index 000000000..d3f160c83
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkScrollbarPeer.java
@@ -0,0 +1,92 @@
+/* GtkScrollbarPeer.java -- Implements ScrollbarPeer with GTK+
+ Copyright (C) 1998, 1999, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Scrollbar;
+import java.awt.event.AdjustmentEvent;
+import java.awt.peer.ScrollbarPeer;
+
+public class GtkScrollbarPeer extends GtkComponentPeer
+ implements ScrollbarPeer
+{
+ void create ()
+ {
+ Scrollbar sb = (Scrollbar) awtComponent;
+
+ create (sb.getOrientation (), sb.getValue (),
+ sb.getMinimum (), sb.getMaximum (),
+ sb.getUnitIncrement (), sb.getBlockIncrement (),
+ sb.getVisibleAmount ());
+ }
+
+ native void create (int orientation, int value,
+ int min, int max, int stepIncr, int pageIncr,
+ int visibleAmount);
+
+ native void connectSignals ();
+
+ public GtkScrollbarPeer (Scrollbar s)
+ {
+ super (s);
+ }
+
+ public native void setLineIncrement(int amount);
+ public native void setPageIncrement(int amount);
+
+ public void setValues(int value, int visible, int min, int max)
+ {
+ Scrollbar sb = (Scrollbar) awtComponent;
+ if (!sb.getValueIsAdjusting())
+ setBarValues(value, visible, min, max);
+ }
+
+ private native void setBarValues(int value, int visible, int min, int max);
+
+ /**
+ * Called from the native site when the scrollbar changed.
+ * Posts a "user generated" AdjustmentEvent to the queue.
+ */
+ protected void postAdjustmentEvent (int type, int value)
+ {
+ Scrollbar bar = (Scrollbar) awtComponent;
+ q().postEvent(new AdjustmentEvent(bar,
+ AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
+ type, value, true));
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkSelection.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkSelection.java
new file mode 100644
index 000000000..78ed69676
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkSelection.java
@@ -0,0 +1,675 @@
+/* GtkClipboard.java - Class representing gtk+ clipboard selection.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.classpath.Pointer;
+
+import java.awt.datatransfer.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import java.awt.Image;
+
+/**
+ * Class representing the gtk+ clipboard selection. This is used when
+ * another program owns the clipboard. Whenever the system clipboard
+ * selection changes we create a new instance to notify the program
+ * that the available flavors might have changed. When requested it
+ * (lazily) caches the targets, and (text, image, or files/uris)
+ * clipboard contents.
+ */
+public class GtkSelection implements Transferable
+{
+ /**
+ * Static lock used for requests of mimetypes and contents retrieval.
+ */
+ static private Object requestLock = new Object();
+
+ /**
+ * Whether we belong to the Clipboard (true) or to the Primary selection.
+ */
+ private final boolean clipboard;
+
+ /**
+ * Whether a request for mimetypes, text, images, uris or byte[] is
+ * currently in progress. Should only be tested or set with
+ * requestLock held. When true no other requests should be made till
+ * it is false again.
+ */
+ private boolean requestInProgress;
+
+ /**
+ * Indicates a requestMimeTypes() call was made and the
+ * corresponding mimeTypesAvailable() callback was triggered.
+ */
+ private boolean mimeTypesDelivered;
+
+ /**
+ * Set and returned by getTransferDataFlavors. Only valid when
+ * mimeTypesDelivered is true.
+ */
+ private DataFlavor[] dataFlavors;
+
+ /**
+ * Indicates a requestText() call was made and the corresponding
+ * textAvailable() callback was triggered.
+ */
+ private boolean textDelivered;
+
+ /**
+ * Set as response to a requestText() call and possibly returned by
+ * getTransferData() for text targets. Only valid when textDelivered
+ * is true.
+ */
+ private String text;
+
+ /**
+ * Indicates a requestImage() call was made and the corresponding
+ * imageAvailable() callback was triggered.
+ */
+ private boolean imageDelivered;
+
+ /**
+ * Set as response to a requestImage() call and possibly returned by
+ * getTransferData() for image targets. Only valid when
+ * imageDelivered is true and image is null.
+ */
+ private Pointer imagePointer;
+
+ /**
+ * Cached image value. Only valid when imageDelivered is
+ * true. Created from imagePointer.
+ */
+ private Image image;
+
+ /**
+ * Indicates a requestUris() call was made and the corresponding
+ * urisAvailable() callback was triggered.
+ */
+ private boolean urisDelivered;
+
+ /**
+ * Set as response to a requestURIs() call. Only valid when
+ * urisDelivered is true
+ */
+ private List<File> uris;
+
+ /**
+ * Indicates a requestBytes(String) call was made and the
+ * corresponding bytesAvailable() callback was triggered.
+ */
+ private boolean bytesDelivered;
+
+ /**
+ * Set as response to a requestBytes(String) call. Only valid when
+ * bytesDelivered is true.
+ */
+ private byte[] bytes;
+
+ /**
+ * Should only be created by the GtkClipboard class. The clipboard
+ * should be either GtkClipboard.clipboard or
+ * GtkClipboard.selection.
+ */
+ GtkSelection(GtkClipboard clipboard)
+ {
+ this.clipboard = (clipboard == GtkClipboard.clipboard);
+ }
+
+ /**
+ * Gets an array of mime-type strings from the gtk+ clipboard and
+ * transforms them into an array of DataFlavors.
+ */
+ public DataFlavor[] getTransferDataFlavors()
+ {
+ DataFlavor[] result;
+ synchronized (requestLock)
+ {
+ // Did we request already and cache the result?
+ if (mimeTypesDelivered)
+ result = (DataFlavor[]) dataFlavors.clone();
+ else
+ {
+ // Wait till there are no pending requests.
+ while (requestInProgress)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+
+ // If nobody else beat us and cached the result we try
+ // ourselves to get it.
+ if (! mimeTypesDelivered)
+ {
+ requestInProgress = true;
+ requestMimeTypes(clipboard);
+ while (! mimeTypesDelivered)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+ requestInProgress = false;
+ }
+ result = dataFlavors;
+ if (! GtkClipboard.canCache)
+ {
+ dataFlavors = null;
+ mimeTypesDelivered = false;
+ }
+ requestLock.notifyAll();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Callback that sets the available DataFlavors[]. Note that this
+ * should not call any code that could need the main gdk lock.
+ */
+ private void mimeTypesAvailable(String[] mimeTypes)
+ {
+ synchronized (requestLock)
+ {
+ if (mimeTypes == null)
+ dataFlavors = new DataFlavor[0];
+ else
+ {
+ // Most likely the mimeTypes include text in which case we add an
+ // extra element.
+ ArrayList<DataFlavor> flavorsList =
+ new ArrayList<DataFlavor>(mimeTypes.length + 1);
+
+ for (int i = 0; i < mimeTypes.length; i++)
+ {
+ try
+ {
+ if (mimeTypes[i] == GtkClipboard.stringMimeType)
+ {
+ // XXX - Fix DataFlavor.getTextPlainUnicodeFlavor()
+ // and also add it to the list.
+ flavorsList.add(DataFlavor.stringFlavor);
+ flavorsList.add(DataFlavor.plainTextFlavor);
+ }
+ else if (mimeTypes[i] == GtkClipboard.imageMimeType)
+ flavorsList.add(DataFlavor.imageFlavor);
+ else if (mimeTypes[i] == GtkClipboard.filesMimeType)
+ flavorsList.add(DataFlavor.javaFileListFlavor);
+ else
+ {
+ // We check the target to prevent duplicates
+ // of the "magic" targets above.
+ DataFlavor target = new DataFlavor(mimeTypes[i]);
+ if (! flavorsList.contains(target))
+ flavorsList.add(target);
+ }
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ cnfe.printStackTrace();
+ }
+ catch (NullPointerException npe)
+ {
+ npe.printStackTrace();
+ }
+ }
+
+ dataFlavors = new DataFlavor[flavorsList.size()];
+ flavorsList.toArray(dataFlavors);
+ }
+
+ mimeTypesDelivered = true;
+ requestLock.notifyAll();
+ }
+ }
+
+ /**
+ * Gets the available data flavors for this selection and checks
+ * that at least one of them is equal to the given DataFlavor.
+ */
+ public boolean isDataFlavorSupported(DataFlavor flavor)
+ {
+ DataFlavor[] dfs = getTransferDataFlavors();
+ for (int i = 0; i < dfs.length; i++)
+ if (flavor.equals(dfs[i]))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Helper method that tests whether we already have the text for the
+ * current gtk+ selection on the clipboard and if not requests it
+ * and waits till it is available.
+ */
+ private String getText()
+ {
+ String result;
+ synchronized (requestLock)
+ {
+ // Did we request already and cache the result?
+ if (textDelivered)
+ result = text;
+ else
+ {
+ // Wait till there are no pending requests.
+ while (requestInProgress)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+
+ // If nobody else beat us we try ourselves to get and
+ // caching the result.
+ if (! textDelivered)
+ {
+ requestInProgress = true;
+ requestText(clipboard);
+ while (! textDelivered)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+ requestInProgress = false;
+ }
+ result = text;
+ if (! GtkClipboard.canCache)
+ {
+ text = null;
+ textDelivered = false;
+ }
+ requestLock.notifyAll();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Callback that sets the available text on the clipboard. Note that
+ * this should not call any code that could need the main gdk lock.
+ */
+ private void textAvailable(String text)
+ {
+ synchronized (requestLock)
+ {
+ this.text = text;
+ textDelivered = true;
+ requestLock.notifyAll();
+ }
+ }
+
+ /**
+ * Helper method that tests whether we already have an image for the
+ * current gtk+ selection on the clipboard and if not requests it
+ * and waits till it is available.
+ */
+ private Image getImage()
+ {
+ Image result;
+ synchronized (requestLock)
+ {
+ // Did we request already and cache the result?
+ if (imageDelivered)
+ result = image;
+ else
+ {
+ // Wait till there are no pending requests.
+ while (requestInProgress)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+
+ // If nobody else beat us we try ourselves to get and
+ // caching the result.
+ if (! imageDelivered)
+ {
+ requestInProgress = true;
+ requestImage(clipboard);
+ while (! imageDelivered)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+ requestInProgress = false;
+ }
+
+ if (imagePointer != null)
+ image = new GtkImage(imagePointer);
+
+ imagePointer = null;
+ result = image;
+ if (! GtkClipboard.canCache)
+ {
+ image = null;
+ imageDelivered = false;
+ }
+ requestLock.notifyAll();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Callback that sets the available image on the clipboard. Note
+ * that this should not call any code that could need the main gdk
+ * lock. Note that we get a Pointer to a GdkPixbuf which we cannot
+ * turn into a real GtkImage at this point. That will be done on the
+ * "user thread" in getImage().
+ */
+ private void imageAvailable(Pointer pointer)
+ {
+ synchronized (requestLock)
+ {
+ this.imagePointer = pointer;
+ imageDelivered = true;
+ requestLock.notifyAll();
+ }
+ }
+
+ /**
+ * Helper method that test whether we already have a list of
+ * URIs/Files and if not requests them and waits till they are
+ * available.
+ */
+ private List<File> getURIs()
+ {
+ List<File> result;
+ synchronized (requestLock)
+ {
+ // Did we request already and cache the result?
+ if (urisDelivered)
+ result = uris;
+ else
+ {
+ // Wait till there are no pending requests.
+ while (requestInProgress)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+
+ // If nobody else beat us we try ourselves to get and
+ // caching the result.
+ if (! urisDelivered)
+ {
+ requestInProgress = true;
+ requestURIs(clipboard);
+ while (! urisDelivered)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+ requestInProgress = false;
+ }
+ result = uris;
+ if (! GtkClipboard.canCache)
+ {
+ uris = null;
+ urisDelivered = false;
+ }
+ requestLock.notifyAll();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Callback that sets the available File list. Note that this should
+ * not call any code that could need the main gdk lock.
+ */
+ private void urisAvailable(String[] uris)
+ {
+ synchronized (requestLock)
+ {
+ if (uris != null && uris.length != 0)
+ {
+ ArrayList<File> list = new ArrayList<File>(uris.length);
+ for (int i = 0; i < uris.length; i++)
+ {
+ try
+ {
+ URI uri = new URI(uris[i]);
+ if (uri.getScheme().equals("file"))
+ list.add(new File(uri));
+ }
+ catch (URISyntaxException use)
+ {
+ }
+ }
+ this.uris = list;
+ }
+
+ urisDelivered = true;
+ requestLock.notifyAll();
+ }
+ }
+
+ /**
+ * Helper method that requests a byte[] for the given target
+ * mime-type flavor and waits till it is available. Note that unlike
+ * the other get methods this one doesn't cache the result since
+ * there are possibly many targets.
+ */
+ private byte[] getBytes(String target)
+ {
+ byte[] result;
+ synchronized (requestLock)
+ {
+ // Wait till there are no pending requests.
+ while (requestInProgress)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+
+ // Request bytes and wait till they are available.
+ requestInProgress = true;
+ requestBytes(clipboard, target);
+ while (! bytesDelivered)
+ {
+ try
+ {
+ requestLock.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+ }
+ result = bytes;
+ bytes = null;
+ bytesDelivered = false;
+ requestInProgress = false;
+
+ requestLock.notifyAll();
+ }
+ return result;
+ }
+
+ /**
+ * Callback that sets the available byte array on the
+ * clipboard. Note that this should not call any code that could
+ * need the main gdk lock.
+ */
+ private void bytesAvailable(byte[] bytes)
+ {
+ synchronized (requestLock)
+ {
+ this.bytes = bytes;
+ bytesDelivered = true;
+ requestLock.notifyAll();
+ }
+ }
+
+ public Object getTransferData(DataFlavor flavor)
+ throws UnsupportedFlavorException
+ {
+ // Note the fall throughs for the "magic targets" if they fail we
+ // try one more time through getBytes().
+ if (flavor.equals(DataFlavor.stringFlavor))
+ {
+ String text = getText();
+ if (text != null)
+ return text;
+ }
+
+ if (flavor.equals(DataFlavor.plainTextFlavor))
+ {
+ String text = getText();
+ if (text != null)
+ return new StringBufferInputStream(text);
+ }
+
+ if (flavor.equals(DataFlavor.imageFlavor))
+ {
+ Image image = getImage();
+ if (image != null)
+ return image;
+ }
+
+ if (flavor.equals(DataFlavor.javaFileListFlavor))
+ {
+ List<File> uris = getURIs();
+ if (uris != null)
+ return uris;
+ }
+
+ byte[] bytes = getBytes(flavor.getMimeType());
+ if (bytes == null)
+ throw new UnsupportedFlavorException(flavor);
+
+ if (flavor.isMimeTypeSerializedObject())
+ {
+ try
+ {
+ ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ return ois.readObject();
+ }
+ catch (IOException ioe)
+ {
+ ioe.printStackTrace();
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ cnfe.printStackTrace();
+ }
+ }
+
+ if (flavor.isRepresentationClassInputStream())
+ return new ByteArrayInputStream(bytes);
+
+ // XXX, need some more conversions?
+
+ throw new UnsupportedFlavorException(flavor);
+ }
+
+ /*
+ * Requests text, Image or an byte[] for a particular target from the
+ * other application. These methods return immediately. When the
+ * content is available the contentLock will be notified through
+ * textAvailable, imageAvailable, urisAvailable or bytesAvailable and the
+ * appropriate field is set.
+ * The clipboard argument is true if we want the Clipboard, and false
+ * if we want the (primary) selection.
+ */
+ private native void requestText(boolean clipboard);
+ private native void requestImage(boolean clipboard);
+ private native void requestURIs(boolean clipboard);
+ private native void requestBytes(boolean clipboard, String target);
+
+ /* Similar to the above but for requesting the supported targets. */
+ private native void requestMimeTypes(boolean clipboard);
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
new file mode 100644
index 000000000..0c7d3a860
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java
@@ -0,0 +1,223 @@
+/* GtkTextAreaPeer.java -- Implements TextAreaPeer with GTK
+ Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Dimension;
+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;
+
+public class GtkTextAreaPeer extends GtkComponentPeer
+ implements TextComponentPeer, TextAreaPeer
+{
+ private static transient int DEFAULT_ROWS = 10;
+ private static transient int DEFAULT_COLS = 80;
+
+ native void create (int width, int height, int scrollbarVisibility);
+
+ /**
+ * Overridden to set Font for text widget inside scrolled window.
+ */
+ protected native void gtkWidgetModifyFont(String name, int style, int size);
+
+ native void gtkWidgetRequestFocus ();
+
+ public native void connectSignals ();
+
+ public native int getCaretPosition ();
+ public native void setCaretPosition (int pos);
+ public native int getSelectionStart ();
+ public native int getSelectionEnd ();
+ public native String getText ();
+ public native void select (int start, int end);
+ public native void setEditable (boolean state);
+ public native void setText (String text);
+
+ public int getIndexAtPoint(int x, int y)
+ {
+ // FIXME
+ return 0;
+ }
+
+ public Rectangle getCharacterBounds (int pos)
+ {
+ // FIXME
+ return null;
+ }
+
+ public long filterEvents (long filter)
+ {
+ // FIXME
+ return filter;
+ }
+
+ void create ()
+ {
+ Font f = awtComponent.getFont ();
+
+ // By default, Sun sets a TextArea's font when its peer is
+ // created. If f != null then the peer's font is set by
+ // GtkComponent.create.
+ if (f == null)
+ {
+ f = new Font ("Dialog", Font.PLAIN, 12);
+ awtComponent.setFont (f);
+ }
+
+ FontMetrics fm = getFontMetrics (f);
+
+ TextArea ta = ((TextArea) awtComponent);
+ int sizeRows = ta.getRows ();
+ int sizeCols = ta.getColumns ();
+
+ sizeRows = sizeRows == 0 ? DEFAULT_ROWS : sizeRows;
+ sizeCols = sizeCols == 0 ? DEFAULT_COLS : sizeCols;
+
+ int width = sizeCols * fm.getMaxAdvance ();
+ int height = sizeRows * (fm.getMaxDescent () + fm.getMaxAscent ());
+
+ create (width, height, ta.getScrollbarVisibility ());
+ setEditable (ta.isEditable ());
+ }
+
+ public GtkTextAreaPeer (TextArea ta)
+ {
+ super (ta);
+
+ setText (ta.getText ());
+ setCaretPosition (0);
+ }
+
+ public native void insert (String str, int pos);
+ public native void replaceRange (String str, int start, int end);
+
+ public Dimension getMinimumSize (int rows, int cols)
+ {
+ return minimumSize (rows == 0 ? DEFAULT_ROWS : rows,
+ cols == 0 ? DEFAULT_COLS : cols);
+ }
+
+ public Dimension getPreferredSize (int rows, int cols)
+ {
+ return preferredSize (rows == 0 ? DEFAULT_ROWS : rows,
+ cols == 0 ? DEFAULT_COLS : cols);
+ }
+
+ native int getHScrollbarHeight ();
+ native int getVScrollbarWidth ();
+
+ // Deprecated
+ public Dimension minimumSize (int rows, int cols)
+ {
+ TextArea ta = ((TextArea) awtComponent);
+ int height = 0;
+ int width = 0;
+
+ if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH
+ || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_HORIZONTAL_ONLY)
+ height = getHScrollbarHeight ();
+
+ if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH
+ || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_VERTICAL_ONLY)
+ width = getVScrollbarWidth ();
+
+ Font f = awtComponent.getFont ();
+ if (f == null)
+ return new Dimension (width, height);
+
+ FontMetrics fm = getFontMetrics (f);
+
+ int sizeRows = rows == 0 ? DEFAULT_ROWS : rows;
+ int sizeCols = cols == 0 ? DEFAULT_COLS : cols;
+
+ width += sizeCols * fm.getMaxAdvance ();
+ height += sizeRows * (fm.getMaxDescent () + fm.getMaxAscent ());
+
+ return new Dimension (width, height);
+ }
+
+ public Dimension preferredSize (int rows, int cols)
+ {
+ TextArea ta = ((TextArea) awtComponent);
+ int height = 0;
+ int width = 0;
+
+ if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH
+ || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_HORIZONTAL_ONLY)
+ height = getHScrollbarHeight ();
+
+ if (ta.getScrollbarVisibility () == TextArea.SCROLLBARS_BOTH
+ || ta.getScrollbarVisibility () == TextArea.SCROLLBARS_VERTICAL_ONLY)
+ width = getVScrollbarWidth ();
+
+ Font f = awtComponent.getFont ();
+ if (f == null)
+ return new Dimension (width, height);
+
+ FontMetrics fm = getFontMetrics (f);
+
+ int sizeRows = rows == 0 ? DEFAULT_ROWS : rows;
+ int sizeCols = cols == 0 ? DEFAULT_COLS : cols;
+
+ width += sizeCols * fm.getMaxAdvance ();
+ height += sizeRows * (fm.getMaxDescent () + fm.getMaxAscent ());
+
+ return new Dimension (width, height);
+ }
+
+ public void replaceText (String str, int start, int end)
+ {
+ replaceRange (str, start, end);
+ }
+
+ public void insertText (String str, int pos)
+ {
+ 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
new file mode 100644
index 000000000..9e62c8e79
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java
@@ -0,0 +1,200 @@
+/* GtkTextFieldPeer.java -- Implements TextFieldPeer with GTK
+ Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.AWTEvent;
+import java.awt.Dimension;
+import java.awt.Font;
+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;
+
+public class GtkTextFieldPeer extends GtkComponentPeer
+ implements TextComponentPeer, TextFieldPeer
+{
+ native void create (int width);
+ native void gtkWidgetSetBackground (int red, int green, int blue);
+ native void gtkWidgetSetForeground (int red, int green, int blue);
+
+ public native void connectSignals ();
+
+ public native int getCaretPosition ();
+ public native void setCaretPosition (int pos);
+ public native int getSelectionStart ();
+ public native int getSelectionEnd ();
+ public native String getText ();
+ public native void select (int start, int end);
+ public native void setEditable (boolean state);
+ public native void setText (String text);
+
+ public int getIndexAtPoint(int x, int y)
+ {
+ // FIXME
+ return 0;
+ }
+
+ public Rectangle getCharacterBounds (int pos)
+ {
+ // FIXME
+ return null;
+ }
+
+ public long filterEvents (long filter)
+ {
+ // FIXME
+ return filter;
+ }
+
+ void create ()
+ {
+ Font f = awtComponent.getFont ();
+
+ // By default, Sun sets a TextField's font when its peer is
+ // created. If f != null then the peer's font is set by
+ // GtkComponent.create.
+ if (f == null)
+ {
+ f = new Font ("Dialog", Font.PLAIN, 12);
+ awtComponent.setFont (f);
+ }
+
+ FontMetrics fm = getFontMetrics (f);
+
+ TextField tf = ((TextField) awtComponent);
+ int cols = tf.getColumns ();
+
+ int text_width = cols * fm.getMaxAdvance ();
+
+ create (text_width);
+
+ setEditable (tf.isEditable ());
+ }
+
+ native int gtkEntryGetBorderWidth ();
+
+ public GtkTextFieldPeer (TextField tf)
+ {
+ super (tf);
+
+ setText (tf.getText ());
+ setCaretPosition (0);
+
+ if (tf.echoCharIsSet ())
+ setEchoChar (tf.getEchoChar ());
+ }
+
+ public Dimension getMinimumSize (int cols)
+ {
+ return minimumSize (cols);
+ }
+
+ public Dimension getPreferredSize (int cols)
+ {
+ return preferredSize (cols);
+ }
+
+ public native void setEchoChar (char c);
+
+ // Deprecated
+ public Dimension minimumSize (int cols)
+ {
+ int dim[] = new int[2];
+
+ gtkWidgetGetPreferredDimensions (dim);
+
+ Font f = awtComponent.getFont ();
+ if (f == null)
+ return new Dimension (2 * gtkEntryGetBorderWidth (), dim[1]);
+
+ FontMetrics fm = getFontMetrics (f);
+
+ int text_width = cols * fm.getMaxAdvance ();
+
+ int width = text_width + 2 * gtkEntryGetBorderWidth ();
+
+ return new Dimension (width, dim[1]);
+ }
+
+ public Dimension preferredSize (int cols)
+ {
+ int dim[] = new int[2];
+
+ gtkWidgetGetPreferredDimensions (dim);
+
+ Font f = awtComponent.getFont ();
+ if (f == null)
+ return new Dimension (2 * gtkEntryGetBorderWidth (), dim[1]);
+
+ FontMetrics fm = getFontMetrics (f);
+
+ int text_width = cols * fm.getMaxAdvance ();
+
+ int width = text_width + 2 * gtkEntryGetBorderWidth ();
+
+ return new Dimension (width, dim[1]);
+ }
+
+ public void setEchoCharacter (char c)
+ {
+ setEchoChar (c);
+ }
+
+ public void handleEvent (AWTEvent e)
+ {
+ if (e.getID () == KeyEvent.KEY_PRESSED)
+ {
+ KeyEvent ke = (KeyEvent) e;
+
+ if (!ke.isConsumed ()
+ && ke.getKeyCode () == KeyEvent.VK_ENTER)
+ postActionEvent (getText (), ke.getModifiersEx ());
+ }
+
+ 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
new file mode 100644
index 000000000..150656511
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java
@@ -0,0 +1,766 @@
+/* GtkToolkit.java -- Implements an AWT Toolkit using GTK for peers
+ Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.classpath.Configuration;
+
+import gnu.java.awt.AWTUtilities;
+import gnu.java.awt.EmbeddedWindow;
+import gnu.java.awt.dnd.GtkMouseDragGestureRecognizer;
+import gnu.java.awt.dnd.peer.gtk.GtkDragSourceContextPeer;
+import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.peer.EmbeddedWindowPeer;
+
+import java.awt.AWTException;
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Checkbox;
+import java.awt.CheckboxMenuItem;
+import java.awt.Choice;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.FileDialog;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Image;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.PopupMenu;
+import java.awt.PrintJob;
+import java.awt.Rectangle;
+import java.awt.ScrollPane;
+import java.awt.Scrollbar;
+import java.awt.TextArea;
+import java.awt.TextField;
+import java.awt.Window;
+import java.awt.datatransfer.Clipboard;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragGestureRecognizer;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.InvalidDnDOperationException;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.font.TextAttribute;
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.awt.peer.CheckboxPeer;
+import java.awt.peer.ChoicePeer;
+import java.awt.peer.DialogPeer;
+import java.awt.peer.FileDialogPeer;
+import java.awt.peer.FontPeer;
+import java.awt.peer.FramePeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.ListPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.MouseInfoPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.PopupMenuPeer;
+import java.awt.peer.RobotPeer;
+import java.awt.peer.ScrollPanePeer;
+import java.awt.peer.ScrollbarPeer;
+import java.awt.peer.TextAreaPeer;
+import java.awt.peer.TextFieldPeer;
+import java.awt.peer.WindowPeer;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.imageio.spi.IIORegistry;
+
+/* This class uses a deprecated method java.awt.peer.ComponentPeer.getPeer().
+ This merits comment. We are basically calling Sun's bluff on this one.
+ We think Sun has deprecated it simply to discourage its use as it is
+ bad programming style. However, we need to get at a component's peer in
+ this class. If getPeer() ever goes away, we can implement a hash table
+ that will keep up with every window's peer, but for now this is faster. */
+
+public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
+{
+ static final Object GTK_LOCK;
+
+ private static EventQueue q;
+
+ static native void gtkInit(int portableNativeSync, Object lock);
+
+ static native void gtkMain();
+
+ static native void gtkQuit();
+
+ /**
+ * Initializes field IDs that are used by native code.
+ */
+ private static native void initIDs();
+
+ /**
+ * True when the field IDs are already initialized, false otherwise.
+ */
+ private static boolean initializedGlobalIDs = false;
+
+ /**
+ * Initializes some global fieldIDs for use in the native code. This is
+ * called by a couple of classes in the GTK peers to ensure that
+ * some necessary stuff is loaded.
+ */
+ static synchronized void initializeGlobalIDs()
+ {
+ if (! initializedGlobalIDs)
+ {
+ initIDs();
+ initializedGlobalIDs = true;
+ }
+ }
+
+ static
+ {
+ if (true) // GCJ LOCAL
+ {
+ System.loadLibrary("gtkpeer");
+ }
+
+ /**
+ * Gotta do that first.
+ */
+ initializeGlobalIDs();
+
+ int portableNativeSync;
+ String portNatSyncProp =
+ System.getProperty("gnu.classpath.awt.gtk.portable.native.sync");
+
+ if (portNatSyncProp == null)
+ portableNativeSync = -1; // unset
+ else if (Boolean.valueOf(portNatSyncProp).booleanValue())
+ portableNativeSync = 1; // true
+ else
+ portableNativeSync = 0; // false
+
+ GTK_LOCK = new String("GTK LOCK");
+ gtkInit(portableNativeSync, GTK_LOCK);
+ }
+
+ public GtkToolkit ()
+ {
+ }
+
+ public native void beep();
+
+ private native void getScreenSizeDimensions(int[] xy);
+
+ public int checkImage (Image image, int width, int height,
+ ImageObserver observer)
+ {
+ int status = ImageObserver.ALLBITS
+ | ImageObserver.WIDTH
+ | ImageObserver.HEIGHT;
+
+ if (image instanceof GtkImage)
+ return ((GtkImage) image).checkImage (observer);
+
+ if (image instanceof AsyncImage)
+ return ((AsyncImage) image).checkImage(observer);
+
+ if (observer != null)
+ observer.imageUpdate (image, status,
+ -1, -1,
+ image.getWidth (observer),
+ image.getHeight (observer));
+
+ return status;
+ }
+
+ /**
+ * Helper to return either a Image -- the argument -- or a
+ * GtkImage with the errorLoading flag set if the argument is null.
+ */
+ static Image imageOrError(Image b)
+ {
+ if (b == null)
+ return GtkImage.getErrorImage();
+ else
+ return b;
+ }
+
+ public Image createImage (String filename)
+ {
+ if (filename.length() == 0)
+ return new GtkImage ();
+
+ Image image;
+ try
+ {
+ image = CairoSurface.getBufferedImage( new GtkImage( filename ) );
+ }
+ catch (IllegalArgumentException iae)
+ {
+ image = null;
+ }
+ return imageOrError(image);
+ }
+
+ public Image createImage (URL url)
+ {
+ return new AsyncImage(url);
+ }
+
+ public Image createImage (ImageProducer producer)
+ {
+ if (producer == null)
+ return null;
+
+ Image image;
+ try
+ {
+ image = CairoSurface.getBufferedImage( new GtkImage( producer ) );
+ }
+ catch (IllegalArgumentException iae)
+ {
+ image = null;
+ }
+ return imageOrError(image);
+ }
+
+ public Image createImage (byte[] imagedata, int imageoffset,
+ int imagelength)
+ {
+ Image image;
+ try
+ {
+ byte[] data = new byte[ imagelength ];
+ System.arraycopy(imagedata, imageoffset, data, 0, imagelength);
+ image = CairoSurface.getBufferedImage( new GtkImage( data ) );
+ }
+ catch (IllegalArgumentException iae)
+ {
+ image = null;
+ }
+ return imageOrError(image);
+ }
+
+ /**
+ * Creates an ImageProducer from the specified URL. The image is assumed
+ * to be in a recognised format.
+ *
+ * @param url URL to read image data from.
+ */
+ public ImageProducer createImageProducer(URL url)
+ {
+ return createImage( url ).getSource();
+ }
+
+ /**
+ * Returns the native color model (which isn't the same as the default
+ * ARGB color model, but doesn't have to be).
+ */
+ public ColorModel getColorModel ()
+ {
+ /* Return the GDK-native ABGR format */
+ return new DirectColorModel(32,
+ 0x000000FF,
+ 0x0000FF00,
+ 0x00FF0000,
+ 0xFF000000);
+ }
+
+ public String[] getFontList ()
+ {
+ return (new String[] { "Dialog",
+ "DialogInput",
+ "Monospaced",
+ "Serif",
+ "SansSerif" });
+ }
+
+ static class LRUCache<K,V> extends LinkedHashMap<K,V>
+ {
+ int max_entries;
+ public LRUCache(int max)
+ {
+ super(max, 0.75f, true);
+ max_entries = max;
+ }
+ protected boolean removeEldestEntry(Map.Entry eldest)
+ {
+ return size() > max_entries;
+ }
+ }
+
+ private LRUCache<Map,ClasspathFontPeer> fontCache =
+ new LRUCache<Map,ClasspathFontPeer>(50);
+ private LRUCache<Object,Image> imageCache = new LRUCache<Object,Image>(50);
+
+ public FontMetrics getFontMetrics (Font font)
+ {
+ return ((GdkFontPeer) font.getPeer()).getFontMetrics(font);
+ }
+
+ public Image getImage (String filename)
+ {
+ if (imageCache.containsKey(filename))
+ return imageCache.get(filename);
+ else
+ {
+ Image im = createImage(filename);
+ imageCache.put(filename, im);
+ return im;
+ }
+ }
+
+ public Image getImage (URL url)
+ {
+ if (imageCache.containsKey(url))
+ return imageCache.get(url);
+ else
+ {
+ Image im = createImage(url);
+ imageCache.put(url, im);
+ return im;
+ }
+ }
+
+ public PrintJob getPrintJob (Frame frame, String jobtitle, Properties props)
+ {
+ SecurityManager sm;
+ sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPrintJobAccess();
+
+ return null;
+ }
+
+ public native int getScreenResolution();
+
+ public Dimension getScreenSize ()
+ {
+ int dim[] = new int[2];
+ getScreenSizeDimensions(dim);
+ return new Dimension(dim[0], dim[1]);
+ }
+
+ public Clipboard getSystemClipboard()
+ {
+ SecurityManager secman = System.getSecurityManager();
+ if (secman != null)
+ secman.checkSystemClipboardAccess();
+
+ return GtkClipboard.getClipboardInstance();
+ }
+
+ public Clipboard getSystemSelection()
+ {
+ SecurityManager secman = System.getSecurityManager();
+ if (secman != null)
+ secman.checkSystemClipboardAccess();
+
+ return GtkClipboard.getSelectionInstance();
+ }
+
+ /**
+ * Prepares a GtkImage. For every other kind of Image it just
+ * assumes the image is already prepared for rendering.
+ */
+ public boolean prepareImage (Image image, int width, int height,
+ ImageObserver observer)
+ {
+ /* GtkImages are always prepared, as long as they're loaded. */
+ if (image instanceof GtkImage)
+ return ((((GtkImage)image).checkImage (observer)
+ & ImageObserver.ALLBITS) != 0);
+
+ if (image instanceof AsyncImage)
+ {
+ AsyncImage aImg = (AsyncImage) image;
+ aImg.addObserver(observer);
+ return aImg.realImage != null;
+ }
+
+ /* Assume anything else is too */
+ return true;
+ }
+
+ public native void sync();
+
+ protected void setComponentState (Component c, GtkComponentPeer cp)
+ {
+ /* Make the Component reflect Peer defaults */
+ if (c.getForeground () == null)
+ c.setForeground (cp.getForeground ());
+ if (c.getBackground () == null)
+ c.setBackground (cp.getBackground ());
+ // if (c.getFont () == null)
+ // c.setFont (cp.getFont ());
+
+ /* Make the Peer reflect the state of the Component */
+ if (! (c instanceof Window))
+ {
+ cp.setCursor (c.getCursor ());
+
+ Rectangle bounds = c.getBounds ();
+ cp.setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
+ cp.setVisible (c.isVisible ());
+ }
+ }
+
+ protected ButtonPeer createButton (Button b)
+ {
+ checkHeadless();
+ return new GtkButtonPeer (b);
+ }
+
+ protected CanvasPeer createCanvas (Canvas c)
+ {
+ checkHeadless();
+ return new GtkCanvasPeer (c);
+ }
+
+ protected CheckboxPeer createCheckbox (Checkbox cb)
+ {
+ checkHeadless();
+ return new GtkCheckboxPeer (cb);
+ }
+
+ protected CheckboxMenuItemPeer createCheckboxMenuItem (CheckboxMenuItem cmi)
+ {
+ checkHeadless();
+ return new GtkCheckboxMenuItemPeer (cmi);
+ }
+
+ protected ChoicePeer createChoice (Choice c)
+ {
+ checkHeadless();
+ return new GtkChoicePeer (c);
+ }
+
+ protected DialogPeer createDialog (Dialog d)
+ {
+ checkHeadless();
+ GtkMainThread.createWindow();
+ return new GtkDialogPeer (d);
+ }
+
+ protected FileDialogPeer createFileDialog (FileDialog fd)
+ {
+ checkHeadless();
+ return new GtkFileDialogPeer (fd);
+ }
+
+ protected FramePeer createFrame (Frame f)
+ {
+ checkHeadless();
+ GtkMainThread.createWindow();
+ return new GtkFramePeer (f);
+ }
+
+ protected LabelPeer createLabel (Label label)
+ {
+ checkHeadless();
+ return new GtkLabelPeer (label);
+ }
+
+ protected ListPeer createList (List list)
+ {
+ checkHeadless();
+ return new GtkListPeer (list);
+ }
+
+ protected MenuPeer createMenu (Menu m)
+ {
+ checkHeadless();
+ return new GtkMenuPeer (m);
+ }
+
+ protected MenuBarPeer createMenuBar (MenuBar mb)
+ {
+ checkHeadless();
+ return new GtkMenuBarPeer (mb);
+ }
+
+ protected MenuItemPeer createMenuItem (MenuItem mi)
+ {
+ checkHeadless();
+ return new GtkMenuItemPeer (mi);
+ }
+
+ protected PanelPeer createPanel (Panel p)
+ {
+ checkHeadless();
+ return new GtkPanelPeer (p);
+ }
+
+ protected PopupMenuPeer createPopupMenu (PopupMenu target)
+ {
+ checkHeadless();
+ return new GtkPopupMenuPeer (target);
+ }
+
+ protected ScrollPanePeer createScrollPane (ScrollPane sp)
+ {
+ checkHeadless();
+ return new GtkScrollPanePeer (sp);
+ }
+
+ protected ScrollbarPeer createScrollbar (Scrollbar sb)
+ {
+ checkHeadless();
+ return new GtkScrollbarPeer (sb);
+ }
+
+ protected TextAreaPeer createTextArea (TextArea ta)
+ {
+ checkHeadless();
+ return new GtkTextAreaPeer (ta);
+ }
+
+ protected TextFieldPeer createTextField (TextField tf)
+ {
+ checkHeadless();
+ return new GtkTextFieldPeer (tf);
+ }
+
+ protected WindowPeer createWindow (Window w)
+ {
+ checkHeadless();
+ GtkMainThread.createWindow();
+ return new GtkWindowPeer (w);
+ }
+
+ public EmbeddedWindowPeer createEmbeddedWindow (EmbeddedWindow w)
+ {
+ checkHeadless();
+ GtkMainThread.createWindow();
+ return new GtkEmbeddedWindowPeer (w);
+ }
+
+ /**
+ * @deprecated part of the older "logical font" system in earlier AWT
+ * implementations. Our newer Font class uses getClasspathFontPeer.
+ */
+ protected FontPeer getFontPeer (String name, int style) {
+ // All fonts get a default size of 12 if size is not specified.
+ return getFontPeer(name, style, 12);
+ }
+
+ /**
+ * Private method that allows size to be set at initialization time.
+ */
+ private FontPeer getFontPeer (String name, int style, int size)
+ {
+ Map<TextAttribute,Object> attrs = new HashMap<TextAttribute,Object>();
+ ClasspathFontPeer.copyStyleToAttrs (style, attrs);
+ ClasspathFontPeer.copySizeToAttrs (size, attrs);
+ return getClasspathFontPeer (name, attrs);
+ }
+
+ /**
+ * Newer method to produce a peer for a Font object, even though Sun's
+ * design claims Font should now be peerless, we do not agree with this
+ * model, hence "ClasspathFontPeer".
+ */
+
+ public ClasspathFontPeer getClasspathFontPeer (String name,
+ Map<?,?> attrs)
+ {
+ Map<Object,Object> keyMap = new HashMap<Object,Object>(attrs);
+ // We don't know what kind of "name" the user requested (logical, face,
+ // family), and we don't actually *need* to know here. The worst case
+ // involves failure to consolidate fonts with the same backend in our
+ // cache. This is harmless.
+ keyMap.put ("GtkToolkit.RequestedFontName", name);
+ if (fontCache.containsKey (keyMap))
+ return fontCache.get (keyMap);
+ else
+ {
+ ClasspathFontPeer newPeer = new GdkFontPeer (name, attrs);
+ fontCache.put (keyMap, newPeer);
+ return newPeer;
+ }
+ }
+
+ protected EventQueue getSystemEventQueueImpl()
+ {
+ synchronized (GtkToolkit.class)
+ {
+ if (q == null)
+ {
+ q = new EventQueue();
+ }
+ }
+ return q;
+ }
+
+ public Cursor createCustomCursor(Image image, Point hotspot, String name)
+ {
+ return new GtkCursor(image, hotspot, name);
+ }
+
+ protected native void loadSystemColors (int[] systemColors);
+
+ public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e)
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new InvalidDnDOperationException();
+ return new GtkDragSourceContextPeer(e);
+ }
+
+ public <T extends DragGestureRecognizer> T
+ createDragGestureRecognizer(Class<T> recognizer, DragSource ds,
+ Component comp, int actions,
+ DragGestureListener l)
+ {
+ if (recognizer.getName().equals("java.awt.dnd.MouseDragGestureRecognizer")
+ && ! GraphicsEnvironment.isHeadless())
+ {
+ GtkMouseDragGestureRecognizer gestureRecognizer
+ = new GtkMouseDragGestureRecognizer(ds, comp, actions, l);
+ gestureRecognizer.registerListeners();
+ return recognizer.cast(gestureRecognizer);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public Map<TextAttribute,?> mapInputMethodHighlight(InputMethodHighlight highlight)
+ {
+ throw new Error("not implemented");
+ }
+
+ public Rectangle getBounds()
+ {
+ int[] dims = new int[2];
+ getScreenSizeDimensions(dims);
+ return new Rectangle(0, 0, dims[0], dims[1]);
+ }
+
+ // ClasspathToolkit methods
+
+ public GraphicsEnvironment getLocalGraphicsEnvironment()
+ {
+ return new GdkGraphicsEnvironment();
+ }
+
+ public Font createFont(int format, InputStream stream)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public RobotPeer createRobot (GraphicsDevice screen) throws AWTException
+ {
+ return new GdkRobotPeer (screen);
+ }
+
+ public boolean getLockingKeyState(int keyCode)
+ {
+ int state = getLockState(keyCode);
+
+ if (state != -1)
+ return state == 1;
+
+ if (AWTUtilities.isValidKey(keyCode))
+ throw new UnsupportedOperationException
+ ("cannot get locking state of key code " + keyCode);
+
+ throw new IllegalArgumentException("invalid key code " + keyCode);
+ }
+
+ protected native int getLockState(int keyCode);
+
+ public void registerImageIOSpis(IIORegistry reg)
+ {
+ GdkPixbufDecoder.registerSpis(reg);
+ }
+
+ protected MouseInfoPeer getMouseInfoPeer()
+ {
+ return new GtkMouseInfoPeer();
+ }
+
+ public boolean isFrameStateSupported(int state)
+ {
+ // GTK supports ICONFIED, NORMAL and MAXIMIZE_BOTH, but
+ // not (yet?) MAXIMIZE_VERT and MAXIMIZE_HORIZ.
+ return state == Frame.NORMAL || state == Frame.ICONIFIED
+ || state == Frame.MAXIMIZED_BOTH;
+ }
+
+ private void checkHeadless()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+ }
+
+ public native int getMouseNumberOfButtons();
+
+ @Override
+ public boolean isModalExclusionTypeSupported
+ (Dialog.ModalExclusionType modalExclusionType)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isModalityTypeSupported(Dialog.ModalityType modalityType)
+ {
+ return false;
+ }
+
+} // class GtkToolkit
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java
new file mode 100644
index 000000000..663839f23
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java
@@ -0,0 +1,207 @@
+/* GtkVolatileImage.java -- wraps an X pixmap
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.ImageCapabilities;
+import java.awt.Point;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.awt.image.VolatileImage;
+import java.awt.image.WritableRaster;
+
+public class GtkVolatileImage extends VolatileImage
+{
+ int width, height;
+ private ImageCapabilities caps;
+
+ final GtkComponentPeer component;
+
+ static ColorModel gdkColorModel = new DirectColorModel(32,
+ 0x000000FF,
+ 0x0000FF00,
+ 0x00FF0000,
+ 0xFF000000);
+
+ /**
+ * Don't touch, accessed from native code.
+ */
+ long nativePointer;
+
+ native long init(GtkComponentPeer component, int width, int height);
+
+ native void destroy(long pointer);
+
+ native int[] nativeGetPixels(long pointer);
+
+ /**
+ * Gets the pixels in the current image from GDK.
+ *
+ * Note that pixels are in 32-bit RGBA, non-premultiplied, which is different
+ * from Cairo's premultiplied ARGB, which is different from Java's standard
+ * non-premultiplied ARGB. Caution is advised when using this method, to
+ * ensure that the data format remains consistent with what you expect.
+ *
+ * @return the current pixels, as reported by GDK.
+ */
+ public int[] getPixels()
+ {
+ return nativeGetPixels(nativePointer);
+ }
+
+ native void nativeCopyArea(long pointer, int x, int y, int w, int h, int dx,
+ int dy );
+ public void copyArea(int x, int y, int w, int h, int dx, int dy)
+ {
+ nativeCopyArea(nativePointer, x, y, w, h, dx, dy);
+ }
+
+ native void nativeDrawVolatile(long pointer, long srcPtr, int x, int y,
+ int w, int h );
+ public void drawVolatile(long srcPtr, int x, int y, int w, int h )
+ {
+ nativeDrawVolatile(nativePointer, srcPtr, x, y, w, h);
+ }
+
+ public GtkVolatileImage(GtkComponentPeer component,
+ int width, int height, ImageCapabilities caps)
+ {
+ this.width = width;
+ this.height = height;
+ this.caps = caps;
+ this.component = component;
+ nativePointer = init( component, width, height );
+ }
+
+ public GtkVolatileImage(int width, int height, ImageCapabilities caps)
+ {
+ this(null, width, height, caps);
+ }
+
+ public GtkVolatileImage(int width, int height)
+ {
+ this(null, width, height, null);
+ }
+
+ public void finalize()
+ {
+ dispose();
+ }
+
+ public void dispose()
+ {
+ destroy(nativePointer);
+ }
+
+ public BufferedImage getSnapshot()
+ {
+ WritableRaster raster = Raster.createWritableRaster(createGdkSampleModel(width, height),
+ new Point(0, 0));
+ raster.setDataElements(0, 0, getPixels());
+ return new BufferedImage(gdkColorModel, raster,
+ gdkColorModel.isAlphaPremultiplied(), null);
+ }
+
+ public Graphics getGraphics()
+ {
+ return createGraphics();
+ }
+
+ public Graphics2D createGraphics()
+ {
+ return new VolatileImageGraphics( this );
+ }
+
+ public int validate(GraphicsConfiguration gc)
+ {
+ return VolatileImage.IMAGE_OK;
+ }
+
+ public boolean contentsLost()
+ {
+ return false;
+ }
+
+ public ImageCapabilities getCapabilities()
+ {
+ return caps;
+ }
+
+ public int getWidth()
+ {
+ return width;
+ }
+
+ public int getHeight()
+ {
+ return height;
+ }
+
+ public int getWidth(java.awt.image.ImageObserver observer)
+ {
+ return width;
+ }
+
+ public int getHeight(java.awt.image.ImageObserver observer)
+ {
+ return height;
+ }
+
+ public Object getProperty(String name, ImageObserver observer)
+ {
+ return null;
+ }
+
+ /**
+ * Creates a SampleModel that matches GDK's native format
+ */
+ protected static SampleModel createGdkSampleModel(int w, int h)
+ {
+ return new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, w, h,
+ new int[]{0x000000FF, 0x0000FF00,
+ 0x00FF0000, 0xFF000000});
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java
new file mode 100644
index 000000000..c8e1bceb7
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java
@@ -0,0 +1,437 @@
+/* GtkWindowPeer.java -- Implements WindowPeer with GTK
+ Copyright (C) 1998, 1999, 2002, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import gnu.java.awt.ComponentReshapeEvent;
+
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.KeyboardFocusManager;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Window;
+import java.awt.event.ComponentEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+import java.awt.peer.WindowPeer;
+
+public class GtkWindowPeer extends GtkContainerPeer
+ implements WindowPeer
+{
+ protected static final int GDK_WINDOW_TYPE_HINT_NORMAL = 0;
+ protected static final int GDK_WINDOW_TYPE_HINT_DIALOG = 1;
+ protected static final int GDK_WINDOW_TYPE_HINT_MENU = 2;
+ protected static final int GDK_WINDOW_TYPE_HINT_TOOLBAR = 3;
+ protected static final int GDK_WINDOW_TYPE_HINT_SPLASHSCREEN = 4;
+ protected static final int GDK_WINDOW_TYPE_HINT_UTILITY = 5;
+ protected static final int GDK_WINDOW_TYPE_HINT_DOCK = 6;
+ protected static final int GDK_WINDOW_TYPE_HINT_DESKTOP = 7;
+
+ protected int windowState = Frame.NORMAL;
+
+ // Cached awt window component location, width and height.
+ private int x, y, width, height;
+
+ native void gtkWindowSetTitle (String title);
+ native void gtkWindowSetResizable (boolean resizable);
+ native void gtkWindowSetModal (boolean modal);
+ native void gtkWindowSetAlwaysOnTop ( boolean alwaysOnTop );
+ native boolean gtkWindowHasFocus();
+ native void realize ();
+
+ public void dispose()
+ {
+ super.dispose();
+ GtkMainThread.destroyWindow();
+ }
+
+ /** Returns the cached width of the AWT window component. */
+ int getX ()
+ {
+ return x;
+ }
+
+ /** Returns the cached width of the AWT window component. */
+ int getY ()
+ {
+ return y;
+ }
+
+ /** Returns the cached width of the AWT window component. */
+ int getWidth ()
+ {
+ return width;
+ }
+
+ /** Returns the cached height of the AWT window component. */
+ int getHeight ()
+ {
+ return height;
+ }
+
+ native void create (int type, boolean decorated, GtkWindowPeer parent);
+
+ void create (int type, boolean decorated)
+ {
+ Window window = (Window) awtComponent;
+ GtkWindowPeer parent_peer = null;
+ Component parent = awtComponent.getParent();
+ x = awtComponent.getX();
+ y = awtComponent.getY();
+ height = awtComponent.getHeight();
+ width = awtComponent.getWidth();
+
+ if (!window.isFocusableWindow())
+ type = GDK_WINDOW_TYPE_HINT_MENU;
+
+ if (parent != null)
+ parent_peer = (GtkWindowPeer) awtComponent.getParent().getPeer();
+
+ create (type, decorated, parent_peer);
+ }
+
+ void create ()
+ {
+ // Create a normal undecorated window.
+ create (GDK_WINDOW_TYPE_HINT_NORMAL, false);
+ }
+
+ void setParent ()
+ {
+ setVisible (awtComponent.isVisible ());
+ setEnabled (awtComponent.isEnabled ());
+ }
+
+ void setVisibleAndEnabled ()
+ {
+ }
+
+ public native void setVisibleNative (boolean b);
+ public native void setVisibleNativeUnlocked (boolean b);
+
+ native void connectSignals ();
+
+ public GtkWindowPeer (Window window)
+ {
+ super (window);
+ // Set reasonable font for the window.
+ window.setFont(new Font("Dialog", Font.PLAIN, 12));
+ }
+
+ public native void toBack();
+ 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);
+ native void nativeSetLocation (int x, int y);
+ native void nativeSetLocationUnlocked (int x, int y);
+
+ // Called from show.
+ protected void setLocation (int x, int y)
+ {
+ nativeSetLocation (x, y);
+ }
+
+ public void setBounds (int x, int y, int width, int height)
+ {
+ if (x != getX() || y != getY() || width != getWidth()
+ || height != getHeight())
+ {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+
+ nativeSetBounds (x, y,
+ width - insets.left - insets.right,
+ height - insets.top - insets.bottom);
+ }
+ }
+
+ public void setTitle (String title)
+ {
+ gtkWindowSetTitle (title);
+ }
+
+ // Called from setResizable
+ protected native void setSize (int width, int height);
+
+ /**
+ * Needed by both GtkFramePeer and GtkDialogPeer subclasses, so
+ * implemented here. But never actually called on a GtkWindowPeer
+ * itself.
+ */
+ public void setResizable (boolean resizable)
+ {
+ // Call setSize; otherwise when resizable is changed from true to
+ // false the window will shrink to the dimensions it had before it
+ // was resizable.
+ x = awtComponent.getX();
+ y = awtComponent.getY();
+ width = awtComponent.getWidth();
+ height = awtComponent.getHeight();
+ setSize (width - insets.left - insets.right,
+ height - insets.top - insets.bottom);
+ gtkWindowSetResizable (resizable);
+ }
+
+ protected void postInsetsChangedEvent (int top, int left,
+ int bottom, int right)
+ {
+ insets.top = top;
+ insets.left = left;
+ insets.bottom = bottom;
+ 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;
+
+ // Update the component's knowledge about the size.
+ // Important: Please look at the big comment in ComponentReshapeEvent
+ // to learn why we did it this way. If you change this code, make
+ // sure that the peer->AWT bounds update still works.
+ // (for instance: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29448 )
+
+ // We do this befor we post the ComponentEvent, because (in Window)
+ // we invalidate() / revalidate() when a ComponentEvent is seen,
+ // and the AWT must already know about the new size then.
+ if (frame_x != this.x || frame_y != this.y || frame_width != this.width
+ || frame_height != this.height)
+ {
+ ComponentReshapeEvent ev = new ComponentReshapeEvent(awtComponent,
+ frame_x,
+ frame_y,
+ frame_width,
+ frame_height);
+ awtComponent.dispatchEvent(ev);
+ }
+
+ if (frame_width != getWidth() || frame_height != getHeight())
+ {
+ this.width = frame_width;
+ this.height = frame_height;
+ q().postEvent(new ComponentEvent(awtComponent,
+ ComponentEvent.COMPONENT_RESIZED));
+ }
+
+ if (frame_x != getX() || frame_y != getY())
+ {
+ this.x = frame_x;
+ this.y = frame_y;
+ q().postEvent(new ComponentEvent(awtComponent,
+ ComponentEvent.COMPONENT_MOVED));
+ }
+
+ }
+
+ public void show ()
+ {
+ x = awtComponent.getX();
+ y = awtComponent.getY();
+ width = awtComponent.getWidth();
+ height = awtComponent.getHeight();
+ setLocation(x, y);
+ setVisible (true);
+ }
+
+ void postWindowEvent (int id, Window opposite, int newState)
+ {
+ if (id == WindowEvent.WINDOW_STATE_CHANGED)
+ {
+ if (windowState != newState)
+ {
+ // Post old styleWindowEvent with WINDOW_ICONIFIED or
+ // WINDOW_DEICONIFIED if appropriate.
+ if ((windowState & Frame.ICONIFIED) != 0
+ && (newState & Frame.ICONIFIED) == 0)
+ q().postEvent(new WindowEvent((Window) awtComponent,
+ WindowEvent.WINDOW_DEICONIFIED,
+ opposite, 0, 0));
+ else if ((windowState & Frame.ICONIFIED) == 0
+ && (newState & Frame.ICONIFIED) != 0)
+ q().postEvent(new WindowEvent((Window) awtComponent,
+ WindowEvent.WINDOW_ICONIFIED,
+ opposite, 0, 0));
+ // Post new-style WindowStateEvent.
+ q().postEvent (new WindowEvent ((Window) awtComponent, id,
+ opposite, windowState, newState));
+ windowState = newState;
+ }
+ }
+ else
+ q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite));
+ }
+
+ /**
+ * Update the always-on-top status of the native window.
+ */
+ public void updateAlwaysOnTop()
+ {
+ gtkWindowSetAlwaysOnTop( ((Window)awtComponent).isAlwaysOnTop() );
+ }
+
+ protected void postExposeEvent (int x, int y, int width, int height)
+ {
+ // Translate GTK co-ordinates, which do not include a window
+ // frame's insets, to AWT co-ordinates, which do include a window
+ // frame's insets. GtkWindowPeer should always have all-zero
+ // insets but GtkFramePeer and GtkDialogPeer insets will be
+ // non-zero.
+ q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
+ new Rectangle (x + insets.left,
+ y + insets.top,
+ width, height)));
+ }
+
+ public boolean requestWindowFocus()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean requestFocus (Component request, boolean temporary,
+ boolean allowWindowFocus, long time)
+ {
+ assert request == awtComponent || isLightweightDescendant(request);
+ boolean retval = false;
+ if (gtkWindowHasFocus())
+ {
+ KeyboardFocusManager kfm =
+ KeyboardFocusManager.getCurrentKeyboardFocusManager();
+ Component currentFocus = kfm.getFocusOwner();
+ if (currentFocus == request)
+ // Nothing to do in this trivial case.
+ retval = true;
+ else
+ {
+ // Requested component is a lightweight descendant of this one
+ // or the actual heavyweight.
+ // Since this (native) component is already focused, we simply
+ // change the actual focus and be done.
+ postFocusEvent(FocusEvent.FOCUS_GAINED, temporary);
+ retval = true;
+ }
+ }
+ else
+ {
+ if (allowWindowFocus)
+ {
+ retval = requestWindowFocus();
+ }
+ }
+ return retval;
+ }
+
+ public Graphics getGraphics ()
+ {
+ Graphics g = super.getGraphics ();
+ // Translate AWT co-ordinates, which include a window frame's
+ // insets, to GTK co-ordinates, which do not include a window
+ // frame's insets. GtkWindowPeer should always have all-zero
+ // insets but GtkFramePeer and GtkDialogPeer insets will be
+ // non-zero.
+ g.translate (-insets.left, -insets.top);
+ return g;
+ }
+
+ protected void postMouseEvent(int id, long when, int mods, int x, int y,
+ int clickCount, boolean popupTrigger)
+ {
+ // Translate AWT co-ordinates, which include a window frame's
+ // insets, to GTK co-ordinates, which do not include a window
+ // frame's insets. GtkWindowPeer should always have all-zero
+ // insets but GtkFramePeer and GtkDialogPeer insets will be
+ // non-zero.
+ super.postMouseEvent (id, when, mods,
+ x + insets.left, y + insets.top,
+ clickCount, popupTrigger);
+ }
+
+ public Point getLocationOnScreen()
+ {
+ int point[] = new int[2];
+ if (Thread.currentThread() == GtkMainThread.mainThread)
+ gtkWindowGetLocationOnScreenUnlocked(point);
+ else
+ gtkWindowGetLocationOnScreen(point);
+ return new Point(point[0], point[1]);
+ }
+
+ // We override this to keep it in sync with our internal
+ // representation.
+ public Rectangle getBounds()
+ {
+ return new Rectangle(x, y, width, height);
+ }
+
+ public void updateIconImages()
+ {
+ // TODO: Implement properly.
+ }
+
+ public void updateMinimumSize()
+ {
+ // TODO: Implement properly.
+ }
+
+ public void setModalBlocked(java.awt.Dialog d, boolean b)
+ {
+ // TODO: Implement properly.
+ }
+
+ public void updateFocusableWindowState()
+ {
+ // TODO: Implement properly.
+ }
+
+ public void setAlwaysOnTop(boolean b)
+ {
+ // TODO: Implement properly.
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
new file mode 100644
index 000000000..2dfcdbdec
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java
@@ -0,0 +1,325 @@
+/* VolatileImageGraphics.java
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Shape;
+import java.awt.Toolkit;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.util.Hashtable;
+
+public class VolatileImageGraphics extends ComponentGraphics
+{
+ private GtkVolatileImage owner;
+ private BufferedImage buffer;
+
+ public VolatileImageGraphics(GtkVolatileImage img)
+ {
+ this.owner = img;
+ cairo_t = initFromVolatile( owner.nativePointer );
+ setup( cairo_t );
+ }
+
+ private VolatileImageGraphics(VolatileImageGraphics copy)
+ {
+ this.owner = copy.owner;
+ cairo_t = initFromVolatile(owner.nativePointer);
+ copy( copy, cairo_t );
+ }
+
+ public void copyAreaImpl(int x, int y, int width, int height, int dx, int dy)
+ {
+ owner.copyArea(x, y, width, height, dx, dy);
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ GraphicsConfiguration conf;
+ if (owner.component != null)
+ {
+ conf = owner.component.getGraphicsConfiguration();
+ }
+ else
+ {
+ return java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+ }
+ return conf;
+ }
+
+ public Graphics create()
+ {
+ return new VolatileImageGraphics( this );
+ }
+
+ public void draw(Shape s)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ super.draw(s);
+
+ // Custom composite
+ else
+ {
+ // Draw operation to temporary buffer
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setColor(this.getColor());
+ g2d.setStroke(this.getStroke());
+ g2d.draw(s);
+
+ drawComposite(s.getBounds2D(), null);
+ }
+ }
+
+ public void fill(Shape s)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ super.fill(s);
+
+ // Custom composite
+ else
+ {
+ // Draw operation to temporary buffer
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setPaint(this.getPaint());
+ g2d.setColor(this.getColor());
+ g2d.fill(s);
+
+ drawComposite(s.getBounds2D(), null);
+ }
+ }
+
+ public void drawGlyphVector(GlyphVector gv, float x, float y)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ super.drawGlyphVector(gv, x, y);
+
+ // Custom composite
+ else
+ {
+ // Draw operation to temporary buffer
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+
+ g2d.setPaint(this.getPaint());
+ g2d.setColor(this.getColor());
+ g2d.drawGlyphVector(gv, x, y);
+
+ Rectangle2D bounds = gv.getLogicalBounds();
+ bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
+ bounds.getWidth(), bounds.getHeight());
+ drawComposite(bounds, null);
+ }
+ }
+
+ protected boolean drawImage(Image img, AffineTransform xform,
+ Color bgcolor, ImageObserver obs)
+ {
+ if (comp == null || comp instanceof AlphaComposite)
+ return super.drawImage(img, xform, bgcolor, obs);
+
+ // Custom composite
+ else
+ {
+ // Get buffered image of source
+ if( !(img instanceof BufferedImage) )
+ {
+ ImageProducer source = img.getSource();
+ if (source == null)
+ return false;
+ img = Toolkit.getDefaultToolkit().createImage(source);
+ }
+ BufferedImage bImg = (BufferedImage) img;
+
+ // Find dimensions of translation
+ Point2D origin = new Point2D.Double(bImg.getMinX(), bImg.getMinY());
+ Point2D pt = new Point2D.Double(bImg.getWidth(), bImg.getHeight());
+ if (xform != null)
+ {
+ origin = xform.transform(origin, origin);
+ pt = xform.transform(pt, pt);
+ }
+
+ // Create buffer and draw image
+ createBuffer();
+
+ Graphics2D g2d = (Graphics2D)buffer.getGraphics();
+ g2d.setRenderingHints(this.getRenderingHints());
+ g2d.drawImage(img, xform, obs);
+
+ // Perform compositing from buffer to screen
+ return drawComposite(new Rectangle2D.Double((int)origin.getX(),
+ (int)origin.getY(),
+ (int)pt.getX(),
+ (int)pt.getY()),
+ obs);
+ }
+ }
+
+ public boolean drawImage(Image img, int x, int y, ImageObserver observer)
+ {
+ if (img instanceof GtkVolatileImage
+ && (comp == null || comp instanceof AlphaComposite))
+ {
+ owner.drawVolatile( ((GtkVolatileImage)img).nativePointer,
+ x, y,
+ ((GtkVolatileImage)img).width,
+ ((GtkVolatileImage)img).height );
+ return true;
+ }
+ return super.drawImage( img, x, y, observer );
+ }
+
+ public boolean drawImage(Image img, int x, int y, int width, int height,
+ ImageObserver observer)
+ {
+ if ((img instanceof GtkVolatileImage)
+ && (comp == null || comp instanceof AlphaComposite))
+ {
+ owner.drawVolatile( ((GtkVolatileImage)img).nativePointer,
+ x, y, width, height );
+ return true;
+ }
+ return super.drawImage( img, x, y, width, height, observer );
+ }
+
+ protected Rectangle2D getRealBounds()
+ {
+ return new Rectangle2D.Double(0, 0, owner.width, owner.height);
+ }
+
+ private boolean drawComposite(Rectangle2D bounds, ImageObserver observer)
+ {
+ // Clip source to visible areas that need updating
+ Rectangle2D clip = this.getClipBounds();
+ Rectangle2D.intersect(bounds, clip, bounds);
+
+ BufferedImage buffer2 = buffer;
+ if (!bounds.equals(buffer2.getRaster().getBounds()))
+ buffer2 = buffer2.getSubimage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(),
+ (int)bounds.getHeight());
+
+ // Get current on-screen pixels (destination) and clip to bounds
+ BufferedImage current = owner.getSnapshot();
+
+ double[] points = new double[] {bounds.getX(), bounds.getY(),
+ bounds.getMaxX(), bounds.getMaxY()};
+ transform.transform(points, 0, points, 0, 2);
+
+ Rectangle2D deviceBounds = new Rectangle2D.Double(points[0], points[1],
+ points[2] - points[0],
+ points[3] - points[1]);
+ Rectangle2D.intersect(deviceBounds, this.getClipInDevSpace(), deviceBounds);
+
+ current = current.getSubimage((int)deviceBounds.getX(),
+ (int)deviceBounds.getY(),
+ (int)deviceBounds.getWidth(),
+ (int)deviceBounds.getHeight());
+
+ // Perform actual composite operation
+ compCtx.compose(buffer2.getRaster(), current.getRaster(),
+ buffer2.getRaster());
+
+ // This MUST call directly into the "action" method in CairoGraphics2D,
+ // not one of the wrappers, to ensure that the composite isn't processed
+ // more than once!
+ Composite oldComp = comp; // so that ComponentGraphics doesn't
+ comp = null; // process the composite again
+ boolean rv = super.drawImage(buffer2,
+ AffineTransform.getTranslateInstance(bounds.getX(),
+ bounds.getY()),
+ null, null);
+ comp = oldComp;
+
+ return rv;
+ }
+
+ private void createBuffer()
+ {
+ if (buffer == null)
+ {
+ WritableRaster rst;
+ rst = Raster.createWritableRaster(GtkVolatileImage.createGdkSampleModel(owner.width,
+ owner.height),
+ new Point(0,0));
+
+ buffer = new BufferedImage(GtkVolatileImage.gdkColorModel, rst,
+ GtkVolatileImage.gdkColorModel.isAlphaPremultiplied(),
+ new Hashtable());
+ }
+ else
+ {
+ Graphics2D g2d = ((Graphics2D)buffer.getGraphics());
+
+ g2d.setBackground(new Color(0,0,0,0));
+ g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
+ }
+ }
+
+ protected ColorModel getNativeCM()
+ {
+ // We should really return GtkVolatileImage.gdkColorModel ,
+ // but CairoGraphics2D doesn't handle alpha premultiplication properly (see
+ // the fixme in drawImage) so we use the naive Cairo model instead to trick
+ // the compositing context.
+ // Because getNativeCM() == getBufferCM() for this peer, it doesn't break.
+ return CairoSurface.cairoCM_pre;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/package.html b/libjava/classpath/gnu/java/awt/peer/gtk/package.html
new file mode 100644
index 000000000..8dd4dd892
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/gtk/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in gnu.java.awt.peer.gtk package.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - gnu.java.awt.peer.gtk</title></head>
+
+<body>
+<p>This package implements the GTK peer for java.awt.</p>
+
+</body>
+</html>
diff --git a/libjava/classpath/gnu/java/awt/peer/headless/HeadlessGraphicsEnvironment.java b/libjava/classpath/gnu/java/awt/peer/headless/HeadlessGraphicsEnvironment.java
new file mode 100644
index 000000000..401b895b8
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/headless/HeadlessGraphicsEnvironment.java
@@ -0,0 +1,118 @@
+/* HeadlessGraphicsEnvironment.java -- A graphics environment for headless mode
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.headless;
+
+import gnu.java.awt.java2d.RasterGraphics;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Locale;
+
+public class HeadlessGraphicsEnvironment
+ extends GraphicsEnvironment
+{
+
+ public Graphics2D createGraphics(BufferedImage image)
+ {
+ Graphics2D g2d;
+ try
+ {
+ // Try to get a CairoGraphics (accellerated) when available. Do this
+ // via reflection to avoid having a hard compile time dependency.
+ Class cairoSurfaceCl =
+ Class.forName("gnu.java.awt.peer.gtk.CairoSurface");
+ Raster raster = image.getRaster();
+ if (cairoSurfaceCl.isInstance(raster))
+ {
+ Method getGraphicsM = cairoSurfaceCl.getMethod("getGraphics",
+ new Class[0]);
+ g2d = (Graphics2D) getGraphicsM.invoke(raster, new Object[0]);
+ }
+ else
+ {
+ Class bigCl =
+ Class.forName("gnu.java.awt.peer.gtk.BufferedImageGraphics");
+ Constructor bigC =
+ bigCl.getConstructor(new Class[]{BufferedImage.class });
+ g2d = (Graphics2D) bigC.newInstance(new Object[]{ image});
+ }
+ }
+ catch (Exception ex)
+ {
+ g2d = new RasterGraphics(image.getRaster(), image.getColorModel());
+ }
+ return g2d;
+ }
+
+ public Font[] getAllFonts()
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public String[] getAvailableFontFamilyNames()
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public String[] getAvailableFontFamilyNames(Locale l)
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public GraphicsDevice getDefaultScreenDevice()
+ {
+ throw new HeadlessException();
+ }
+
+ public GraphicsDevice[] getScreenDevices()
+ {
+ throw new HeadlessException();
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/headless/HeadlessToolkit.java b/libjava/classpath/gnu/java/awt/peer/headless/HeadlessToolkit.java
new file mode 100644
index 000000000..58b5f3334
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/headless/HeadlessToolkit.java
@@ -0,0 +1,385 @@
+/* HeadlessToolkit.java -- A toolkit for headless mode
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.headless;
+
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.EmbeddedWindow;
+import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.peer.EmbeddedWindowPeer;
+
+import java.awt.AWTException;
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Checkbox;
+import java.awt.CheckboxMenuItem;
+import java.awt.Choice;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.FileDialog;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Image;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.PopupMenu;
+import java.awt.PrintJob;
+import java.awt.ScrollPane;
+import java.awt.Scrollbar;
+import java.awt.TextArea;
+import java.awt.TextField;
+import java.awt.Window;
+import java.awt.datatransfer.Clipboard;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.ColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.awt.peer.CheckboxPeer;
+import java.awt.peer.ChoicePeer;
+import java.awt.peer.DialogPeer;
+import java.awt.peer.FileDialogPeer;
+import java.awt.peer.FontPeer;
+import java.awt.peer.FramePeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.ListPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.PopupMenuPeer;
+import java.awt.peer.RobotPeer;
+import java.awt.peer.ScrollPanePeer;
+import java.awt.peer.ScrollbarPeer;
+import java.awt.peer.TextAreaPeer;
+import java.awt.peer.TextFieldPeer;
+import java.awt.peer.WindowPeer;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Map;
+import java.util.Properties;
+
+public class HeadlessToolkit
+ extends ClasspathToolkit
+{
+
+ /**
+ * The graphics environment for headless graphics.
+ */
+ private HeadlessGraphicsEnvironment graphicsEnv;
+
+ public void beep()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public int checkImage(Image image, int width, int height,
+ ImageObserver observer)
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ protected ButtonPeer createButton(Button target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected CanvasPeer createCanvas(Canvas target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected CheckboxPeer createCheckbox(Checkbox target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected ChoicePeer createChoice(Choice target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected DialogPeer createDialog(Dialog target)
+ {
+ throw new HeadlessException();
+ }
+
+ public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e)
+ {
+ throw new HeadlessException();
+ }
+
+ protected FileDialogPeer createFileDialog(FileDialog target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected FramePeer createFrame(Frame target)
+ {
+ throw new HeadlessException();
+ }
+
+ public Image createImage(String filename)
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public Image createImage(URL url)
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public Image createImage(ImageProducer producer)
+ {
+ // FIXME: Implement.
+ return null;
+ }
+
+ public Image createImage(byte[] data, int offset, int len)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ protected LabelPeer createLabel(Label target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected ListPeer createList(List target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected MenuPeer createMenu(Menu target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected MenuBarPeer createMenuBar(MenuBar target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected MenuItemPeer createMenuItem(MenuItem target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected PanelPeer createPanel(Panel target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected PopupMenuPeer createPopupMenu(PopupMenu target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected ScrollPanePeer createScrollPane(ScrollPane target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected ScrollbarPeer createScrollbar(Scrollbar target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected TextAreaPeer createTextArea(TextArea target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected TextFieldPeer createTextField(TextField target)
+ {
+ throw new HeadlessException();
+ }
+
+ protected WindowPeer createWindow(Window target)
+ {
+ throw new HeadlessException();
+ }
+
+ public ColorModel getColorModel()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String[] getFontList()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public FontMetrics getFontMetrics(Font name)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ protected FontPeer getFontPeer(String name, int style)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Image getImage(String name)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Image getImage(URL url)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public PrintJob getPrintJob(Frame frame, String title, Properties props)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getScreenResolution()
+ {
+ throw new HeadlessException();
+ }
+
+ public Dimension getScreenSize()
+ {
+ throw new HeadlessException();
+ }
+
+ public Clipboard getSystemClipboard()
+ {
+ throw new HeadlessException();
+ }
+
+ protected EventQueue getSystemEventQueueImpl()
+ {
+ throw new HeadlessException();
+ }
+
+ public Map mapInputMethodHighlight(InputMethodHighlight highlight)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean prepareImage(Image image, int width, int height,
+ ImageObserver observer)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void sync()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public EmbeddedWindowPeer createEmbeddedWindow(EmbeddedWindow w)
+ {
+ throw new HeadlessException();
+ }
+
+ public Font createFont(int format, InputStream stream)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public RobotPeer createRobot(GraphicsDevice screen) throws AWTException
+ {
+ throw new HeadlessException();
+ }
+
+ public ClasspathFontPeer getClasspathFontPeer(String name, Map attrs)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public GraphicsEnvironment getLocalGraphicsEnvironment()
+ {
+ if (graphicsEnv == null)
+ graphicsEnv = new HeadlessGraphicsEnvironment();
+ return graphicsEnv;
+ }
+
+ @Override
+ public boolean isModalExclusionTypeSupported
+ (Dialog.ModalExclusionType modalExclusionType)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isModalityTypeSupported(Dialog.ModalityType modalityType)
+ {
+ return false;
+ }
+
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/package.html b/libjava/classpath/gnu/java/awt/peer/package.html
new file mode 100644
index 000000000..846759a28
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/package.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in gnu.java.awt.peer package.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+<head><title>GNU Classpath - gnu.java.awt.peer</title></head>
+
+<body>
+<p></p>
+
+</body>
+</html>
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/MainQtThread.java b/libjava/classpath/gnu/java/awt/peer/qt/MainQtThread.java
new file mode 100644
index 000000000..bee979ac7
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/MainQtThread.java
@@ -0,0 +1,84 @@
+/* MainQtThread.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+/**
+ * This Thread is the main Qt thread.
+ *
+ * It doesn't appear to do much here, since all custom code executed by
+ * this thread is injected into Qt's main event loop through the (native)
+ * MainThreadInterface class.
+ */
+public class MainQtThread extends Thread
+{
+ long QApplicationPointer;
+ long mainThreadInterface;
+ String theme;
+ private boolean running;
+ private boolean doublebuffer;
+
+ public MainQtThread( String theme, boolean doublebuffer )
+ {
+ this.theme = theme;
+ this.doublebuffer = doublebuffer;
+ running = false;
+ }
+
+ public boolean isRunning()
+ {
+ return running;
+ }
+
+ /**
+ * Creates the QApplication
+ */
+ public native long init(String theme, boolean doublebuffer);
+
+ /**
+ * Runs the QApplication (doesn't return.)
+ */
+ public native void exec(long ptr);
+
+ public void run()
+ {
+ QApplicationPointer = init(theme, doublebuffer);
+ running = true;
+ exec(QApplicationPointer);
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/NativeWrapper.java b/libjava/classpath/gnu/java/awt/peer/qt/NativeWrapper.java
new file mode 100644
index 000000000..706e0df6c
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/NativeWrapper.java
@@ -0,0 +1,43 @@
+/* NativeWrapper.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+public class NativeWrapper
+{
+ protected long nativeObject;
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QMatrix.java b/libjava/classpath/gnu/java/awt/peer/qt/QMatrix.java
new file mode 100644
index 000000000..ca4d55b59
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QMatrix.java
@@ -0,0 +1,72 @@
+/* QMatrix.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.geom.AffineTransform;
+
+/**
+ * A simple wrapper class for a QMatrix,
+ * interfacing it to an AffineTransform.
+ */
+public class QMatrix extends NativeWrapper
+{
+
+ public QMatrix( AffineTransform t )
+ {
+ double[] matrix = new double[6];
+ t.getMatrix( matrix );
+ init( matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5] );
+ }
+
+ private native void init(double m00, double m10, double m01, double m11,
+ double m02, double m12 );
+
+ private native double[] getMatrix();
+
+ public AffineTransform getTransform()
+ {
+ return new AffineTransform( getMatrix() );
+ }
+
+ public native void dispose();
+
+ public void finalize()
+ {
+ dispose();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QPainterPath.java b/libjava/classpath/gnu/java/awt/peer/qt/QPainterPath.java
new file mode 100644
index 000000000..848b10497
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QPainterPath.java
@@ -0,0 +1,140 @@
+/* QPainterPath.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+import java.awt.geom.GeneralPath;
+
+/**
+ * A simple wrapper class for a QPainterPath,
+ * createable from an AWT Shape
+ */
+public class QPainterPath extends NativeWrapper
+{
+ QPainterPath()
+ {
+ }
+
+ public QPainterPath( Shape s )
+ {
+ PathIterator pi = s.getPathIterator( new AffineTransform() );
+ double[] coords = new double[6];
+
+ init( pi.getWindingRule() );
+
+ while( !pi.isDone() )
+ {
+ switch( pi.currentSegment(coords) )
+ {
+ case PathIterator.SEG_MOVETO:
+ moveTo( coords[0], coords[1] );
+ break;
+
+ case PathIterator.SEG_CLOSE:
+ close();
+ break;
+
+ case PathIterator.SEG_LINETO:
+ lineTo( coords[0], coords[1] );
+ break;
+
+ case PathIterator.SEG_QUADTO:
+ quadTo( coords[0], coords[1], coords[2], coords[3] );
+ break;
+
+ case PathIterator.SEG_CUBICTO:
+ cubicTo( coords[0], coords[1],
+ coords[2], coords[3],
+ coords[4], coords[5] );
+ break;
+ }
+ pi.next();
+ }
+ }
+
+ /**
+ * Constructor for rectangles.
+ */
+ public QPainterPath( double x, double y, double w, double h )
+ {
+ init(PathIterator.WIND_EVEN_ODD);
+ moveTo( x, y );
+ lineTo( x + w, y );
+ lineTo( x + w, y + h );
+ lineTo( x , y + h );
+ lineTo( x, y );
+ close();
+ }
+
+ /**
+ * Constructor for lines.
+ */
+ public QPainterPath( double x1, double y1, double x2, double y2, boolean s )
+ {
+ init(PathIterator.WIND_EVEN_ODD);
+ moveTo( x1, y1 );
+ lineTo( x2, y2 );
+ }
+
+ /**
+ * Returns the QPainterPath as a GeneralPath
+ */
+ public native GeneralPath getPath();
+
+ private native void init(int windingRule);
+
+ private native void moveTo(double x, double y);
+
+ private native void close();
+
+ private native void lineTo(double x, double y);
+
+ private native void quadTo(double x1, double y1, double x2, double y2);
+
+ private native void cubicTo(double x1, double y1, double x2, double y2,
+ double x3, double y3);
+
+ public native void dispose();
+
+ public void finalize()
+ {
+ dispose();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QPen.java b/libjava/classpath/gnu/java/awt/peer/qt/QPen.java
new file mode 100644
index 000000000..aee308c26
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QPen.java
@@ -0,0 +1,70 @@
+/* QPen.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Stroke;
+import java.awt.BasicStroke;
+
+/**
+ * A simple wrapper class for a QPen,
+ * interfacing it to an BasicStroke.
+ */
+public class QPen extends NativeWrapper
+{
+
+ public QPen( Stroke stroke )
+ {
+ if( !( stroke instanceof BasicStroke ) )
+ throw new IllegalArgumentException("Not a basic stroke.");
+
+ BasicStroke s = (BasicStroke)stroke;
+ if(s.getDashArray() != null)
+ throw new IllegalArgumentException("Can't handle dashed strokes.");
+
+ init(s.getLineWidth(), s.getEndCap(), s.getLineJoin(), s.getMiterLimit());
+ }
+
+ private native void init(double width, int cap, int join, double miterlimit);
+
+ public native void dispose();
+
+ public void finalize()
+ {
+ dispose();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtAudioClip.java b/libjava/classpath/gnu/java/awt/peer/qt/QtAudioClip.java
new file mode 100644
index 000000000..ae2e350eb
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtAudioClip.java
@@ -0,0 +1,110 @@
+/* QtAudioClip.java -- Qt implementation of the applet AudioClip interface
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.applet.AudioClip;
+import java.awt.Toolkit;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * Implementation of the applet AudioClip interface on a Qt
+ * QSound object.
+ */
+public class QtAudioClip extends NativeWrapper implements AudioClip
+{
+ private static Toolkit t = null;
+
+ public QtAudioClip(String filename)
+ {
+ checkForQt();
+ File f = new File(filename);
+ try
+ {
+ String fn = f.getCanonicalPath();
+ loadClip( fn );
+ }
+ catch(IOException e)
+ {
+ }
+ }
+
+ public QtAudioClip(URL url)
+ {
+
+ }
+
+ private native void loadClip(String filename);
+
+ private native void play(boolean looped);
+
+ private native boolean isAvailable();
+
+ /**
+ * Checks that Qt and sound is available.
+ */
+ private void checkForQt()
+ {
+ if( t == null )
+ t = Toolkit.getDefaultToolkit();
+ if( !( t instanceof QtToolkit) )
+ throw new IllegalStateException("This requires Qt peers.");
+ }
+
+ // *************** Public methods *******************
+
+ public void loop()
+ {
+ play( true );
+ }
+
+ public void play()
+ {
+ play( false );
+ }
+
+ public native void stop();
+
+ public native void dispose();
+
+ public void finalize()
+ {
+ dispose();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtButtonPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtButtonPeer.java
new file mode 100644
index 000000000..6722eb285
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtButtonPeer.java
@@ -0,0 +1,75 @@
+/* QtButtonPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Button;
+import java.awt.event.ActionEvent;
+import java.awt.peer.ButtonPeer;
+
+public class QtButtonPeer extends QtComponentPeer implements ButtonPeer
+{
+ public QtButtonPeer( QtToolkit kit, Button owner )
+ {
+ super( kit, owner );
+ }
+
+ public native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ setLabel( ((Button)owner).getLabel() );
+ }
+
+ /**
+ * Callback for button click events
+ */
+ void fireClick(int modifiers)
+ {
+ ActionEvent e = new ActionEvent(owner,
+ ActionEvent.ACTION_PERFORMED,
+ ((Button)owner).getActionCommand(),
+ System.currentTimeMillis(),
+ modifiers);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ // ************ Public methods *********************
+
+ public native void setLabel( String label );
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtCanvasPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtCanvasPeer.java
new file mode 100644
index 000000000..2367cd066
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtCanvasPeer.java
@@ -0,0 +1,65 @@
+/* QtCanvasPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Canvas;
+import java.awt.Dimension;
+import java.awt.peer.CanvasPeer;
+
+public class QtCanvasPeer extends QtComponentPeer implements CanvasPeer
+{
+ public QtCanvasPeer( QtToolkit kit, Canvas owner )
+ {
+ super( kit, owner );
+ }
+
+ public native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ }
+
+ /**
+ * Overloaded, because a Canvas doesn't have a preferred size.
+ */
+ public Dimension getPreferredSize()
+ {
+ return owner.getSize();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtCheckboxPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtCheckboxPeer.java
new file mode 100644
index 000000000..37fb51c48
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtCheckboxPeer.java
@@ -0,0 +1,111 @@
+/* QtCheckboxPeer.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Checkbox;
+import java.awt.CheckboxGroup;
+import java.awt.event.ItemEvent;
+import java.awt.peer.CheckboxPeer;
+import java.util.WeakHashMap;
+
+public class QtCheckboxPeer extends QtComponentPeer implements CheckboxPeer
+{
+ private CheckboxGroup group;
+
+ // Map QButtonGroup<->CheckboxGroup
+ private static WeakHashMap groupMap;
+
+ static
+ {
+ groupMap = new WeakHashMap();
+ }
+
+ public QtCheckboxPeer( QtToolkit kit, Checkbox owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ setCheckboxGroup( ((Checkbox)owner).getCheckboxGroup() );
+ setLabel( ((Checkbox)owner).getLabel() );
+ setState( ((Checkbox)owner).getState() );
+ }
+
+ private void fireToggle(boolean checked)
+ {
+ if (group == null)
+ ((Checkbox)owner).setState( checked );
+ else
+ if ( checked )
+ group.setSelectedCheckbox((Checkbox)owner);
+
+ int sel = checked ? ItemEvent.SELECTED : ItemEvent.DESELECTED;
+ ItemEvent e = new ItemEvent((Checkbox)owner,
+ ItemEvent.ITEM_STATE_CHANGED,
+ ((Checkbox)owner).getLabel(),
+ sel);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ // ************ Public methods *********************
+
+ public void setCheckboxGroup( CheckboxGroup group )
+ {
+ if(this.group == group)
+ return;
+
+ // if we change from a checkbox to a radio button or vice versa
+ if((this.group == null) != (group == null))
+ {
+ this.group = group;
+ callInit();
+ setup();
+ }
+
+ this.group = group;
+ }
+
+ public native void setLabel( String label );
+
+ public native void setState( boolean state );
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtChoicePeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtChoicePeer.java
new file mode 100644
index 000000000..d279468cd
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtChoicePeer.java
@@ -0,0 +1,93 @@
+/* QtChoicePeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Choice;
+import java.awt.event.ItemEvent;
+import java.awt.peer.ChoicePeer;
+
+public class QtChoicePeer extends QtComponentPeer implements ChoicePeer
+{
+ public QtChoicePeer( QtToolkit kit, Choice owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+
+ Choice c = (Choice) owner;
+ int n = c.getItemCount();
+ for ( int i = 0; i < n ; i++ )
+ add( c.getItem( i ), i );
+ select( c.getSelectedIndex() );
+ }
+
+ private void fireChoice( int index )
+ {
+ ((Choice)owner).select( index );
+ ItemEvent e = new ItemEvent((Choice)owner,
+ ItemEvent.ITEM_STATE_CHANGED,
+ ((Choice)owner).getItem(index),
+ ItemEvent.SELECTED);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ // ************ Public methods *********************
+
+ public native void add( String item, int index );
+
+ public void addItem( String item, int index )
+ {
+ add(item, index);
+ }
+
+ public native void remove( int index );
+
+ public void removeAll()
+ {
+ int n = ((Choice)owner).getItemCount();
+ for (int i = 0; i < n; i++)
+ remove( i );
+ }
+
+ public native void select( int index );
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtComponentGraphics.java b/libjava/classpath/gnu/java/awt/peer/qt/QtComponentGraphics.java
new file mode 100644
index 000000000..27e12e659
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtComponentGraphics.java
@@ -0,0 +1,120 @@
+/* QtComponentGraphics.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Color;
+import java.awt.GraphicsConfiguration;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+/**
+ * QtComponentPainter is a Graphics2D context for painting directly to AWT
+ * components. They require an existing QPainter object (the one passed into
+ * the native paint method), and are created there (ONLY).
+ *
+ * Since this context does direct on-screen drawing it is NOT thread-safe,
+ * and should NOT be used outside the thread in which it was created.
+ *
+ * In other words,
+ * this is intended for use by QtComponentPeer.paintEvent() only.
+ *
+ */
+public class QtComponentGraphics extends QtGraphics
+{
+ private QtComponentPeer peer;
+
+ /**
+ * Creates a new ComponentGraphics from an *existing* QPainter object.
+ *
+ * @param ptr the pointer to the QPainter object.
+ */
+ public QtComponentGraphics(long ptr, QtComponentPeer component,
+ int x, int y, int w, int h)
+ {
+ nativeObject = ptr;
+ peer = component;
+
+ Rectangle r = new Rectangle(x, y, w, h);
+ initialClip = r;
+
+ setAlpha( 1.0 );
+ Color c = component.owner.getBackground();
+ if(c == null)
+ setBackground(Color.white);
+ else
+ setBackground( c );
+
+ c = component.owner.getForeground();
+ if(c == null)
+ setColor( Color.black );
+ else
+ setColor( c );
+ setup();
+ setClip( initialClip );
+ }
+
+ /**
+ * Copying constructor
+ */
+ QtComponentGraphics( QtComponentGraphics g )
+ {
+ super( g ); // Slalom is fun
+ }
+
+ public Graphics create()
+ {
+ return new QtComponentGraphics( this );
+ }
+
+ /**
+ * This is a tricky one
+ */
+ public void copyArea(int x, int y, int width, int height,
+ int dx, int dy)
+ {
+ // FIXME
+ }
+
+ /**
+ * Returns the GraphicsConfiguration of the context component.
+ */
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ return peer.getGraphicsConfiguration();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtComponentPeer.java
new file mode 100644
index 000000000..16149b2e6
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtComponentPeer.java
@@ -0,0 +1,834 @@
+/* QtComponentPeer.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.BufferCapabilities;
+import java.awt.Component;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Image;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.KeyboardFocusManager;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.ContainerPeer;
+import java.awt.image.ColorModel;
+import java.awt.image.VolatileImage;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.event.ComponentEvent; // 100%
+import java.awt.event.FocusEvent; // 100%
+import java.awt.event.InputEvent; // (abstract)
+import java.awt.event.KeyEvent; // 2/3
+import java.awt.event.MouseEvent; // 70%?
+import java.awt.event.PaintEvent; // Yup.
+import java.awt.event.WindowEvent; // 2/ 12
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class QtComponentPeer extends NativeWrapper implements ComponentPeer
+{
+
+ /**
+ * Popup trigger button, may differ between platforms
+ */
+ protected static final int POPUP_TRIGGER = 3;
+
+ /**
+ * The toolkit which manufactured this peer.
+ */
+ protected QtToolkit toolkit;
+
+ /**
+ * The component which owns this peer.
+ */
+ Component owner;
+
+ /**
+ * Classpath updates our eventMask.
+ */
+ private long eventMask;
+
+ /**
+ * if the thing has mouse motion listeners or not.
+ */
+ private boolean hasMotionListeners;
+
+ /**
+ * The component's double buffer for off-screen drawing.
+ */
+ protected QtImage backBuffer;
+
+ protected long qtApp;
+
+ private boolean settingUp;
+
+ private boolean ignoreResize = false;
+
+ QtComponentPeer( QtToolkit kit, Component owner )
+ {
+ this.owner = owner;
+ this.toolkit = kit;
+ qtApp = QtToolkit.guiThread.QApplicationPointer;
+ nativeObject = 0;
+ synchronized(this)
+ {
+ callInit(); // Calls the init method FROM THE MAIN THREAD.
+ try
+ {
+ wait(); // Wait for the thing to be created.
+ }
+ catch(InterruptedException e)
+ {
+ }
+ }
+ setup();
+ hasMotionListeners = false;
+ }
+
+ protected native void callInit();
+
+ /**
+ * Init does the creation of native widgets, it is therefore
+ * called from the main thread. (the constructor waits for this to happen.)
+ */
+ protected void init()
+ {
+ }
+
+ protected void setup()
+ {
+ settingUp = true;
+ if (owner != null)
+ {
+ if (owner instanceof javax.swing.JComponent)
+ setBackground(owner.getBackground());
+ else
+ owner.setBackground(getNativeBackground());
+
+ if (owner.getForeground() != null)
+ setForeground(owner.getForeground());
+ else
+ setForeground( Color.black );
+
+ if (owner.getCursor() != null)
+ if (owner.getCursor().getType() != Cursor.DEFAULT_CURSOR)
+ setCursor(owner.getCursor());
+
+ if (owner.getFont() != null)
+ setFont(owner.getFont());
+
+ setEnabled( owner.isEnabled() );
+
+ backBuffer = null;
+ updateBounds();
+
+ setVisible( owner.isVisible() );
+ QtToolkit.repaintThread.queueComponent(this);
+ }
+ settingUp = false;
+ }
+
+ native void QtUpdate();
+ native void QtUpdateArea( int x, int y, int w, int h );
+ private synchronized native void disposeNative();
+ private native void setGround( int r, int g, int b, boolean isForeground );
+ private native void setBoundsNative( int x, int y, int width, int height );
+ private native void setCursor( int ctype );
+ private native Color getNativeBackground();
+ private native void setFontNative( QtFontPeer fp );
+ private native int whichScreen();
+ private native void reparentNative( QtContainerPeer parent );
+ private native void getLocationOnScreenNative( Point p );
+
+ private boolean drawableComponent()
+ {
+ return ((this instanceof QtContainerPeer &&
+ !(this instanceof QtScrollPanePeer)) ||
+ (this instanceof QtCanvasPeer));
+ }
+
+ void updateBounds()
+ {
+ Rectangle r = owner.getBounds();
+ setBounds( r.x, r.y, r.width, r.height );
+ }
+
+ synchronized void updateBackBuffer(int width, int height)
+ {
+ if(width <= 0 || height <= 0)
+ return;
+
+ if( !drawableComponent() && backBuffer == null)
+ return;
+
+ if( backBuffer != null )
+ {
+ if( width < backBuffer.width && height < backBuffer.height )
+ return;
+ backBuffer.dispose();
+ }
+ backBuffer = new QtImage(width, height);
+ }
+
+
+ // ************ Event methods *********************
+
+ /**
+ * Window closing event
+ */
+ protected void closeEvent()
+ {
+ if (owner instanceof Window)
+ {
+ WindowEvent e = new WindowEvent((Window)owner,
+ WindowEvent.WINDOW_CLOSING);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+ }
+
+ protected void enterEvent(int modifiers, int x, int y, int dummy)
+ {
+ MouseEvent e = new MouseEvent(owner,
+ MouseEvent.MOUSE_ENTERED,
+ System.currentTimeMillis(),
+ (modifiers & 0x2FF), x, y, 0, false);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ protected void focusInEvent()
+ {
+ FocusEvent e = new FocusEvent(owner, FocusEvent.FOCUS_GAINED);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ protected void focusOutEvent()
+ {
+ FocusEvent e = new FocusEvent(owner, FocusEvent.FOCUS_LOST);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ protected void keyPressEvent(int modifiers, int code, int unicode, int dummy)
+ {
+ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
+ KeyEvent e = new KeyEvent(owner,
+ KeyEvent.KEY_PRESSED,
+ System.currentTimeMillis(),
+ modifiers, code, (char)(unicode & 0xFFFF),
+ KeyEvent.KEY_LOCATION_UNKNOWN);
+ if (!manager.dispatchEvent (e))
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ protected void keyReleaseEvent(int modifiers, int code, int unicode, int dummy)
+ {
+ KeyEvent e = new KeyEvent(owner,
+ KeyEvent.KEY_RELEASED,
+ System.currentTimeMillis(),
+ modifiers, code, (char)(unicode & 0xFFFF),
+ KeyEvent.KEY_LOCATION_UNKNOWN);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ protected void leaveEvent(int modifiers, int x, int y, int dummy)
+ {
+ MouseEvent e = new MouseEvent(owner,
+ MouseEvent.MOUSE_EXITED,
+ System.currentTimeMillis(),
+ (modifiers & 0x2FF), x, y, 0, false);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ // FIXME: Coalesce press-release events into clicks.
+ protected void mouseDoubleClickEvent( int modifiers, int x, int y, int clickCount)
+ {
+ if( (eventMask & AWTEvent.MOUSE_EVENT_MASK) == 0 )
+ return;
+ int button = 0;
+ if((modifiers & InputEvent.BUTTON1_DOWN_MASK) ==
+ InputEvent.BUTTON1_DOWN_MASK) button = 1;
+ if((modifiers & InputEvent.BUTTON2_DOWN_MASK) ==
+ InputEvent.BUTTON2_DOWN_MASK) button = 2;
+ if((modifiers & InputEvent.BUTTON3_DOWN_MASK) ==
+ InputEvent.BUTTON3_DOWN_MASK) button = 3;
+ MouseEvent e = new MouseEvent(owner,
+ MouseEvent.MOUSE_CLICKED,
+ System.currentTimeMillis(),
+ (modifiers & 0x2FF), x, y, clickCount,
+ false, button);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ protected void mouseMoveEvent( int modifiers, int x, int y, int clickCount)
+ {
+ if( (eventMask & AWTEvent.MOUSE_EVENT_MASK) == 0 )
+ return;
+
+ int button = 0;
+ if((modifiers & InputEvent.BUTTON1_DOWN_MASK) ==
+ InputEvent.BUTTON1_DOWN_MASK) button = 1;
+ if((modifiers & InputEvent.BUTTON2_DOWN_MASK) ==
+ InputEvent.BUTTON2_DOWN_MASK) button = 2;
+ if((modifiers & InputEvent.BUTTON3_DOWN_MASK) ==
+ InputEvent.BUTTON3_DOWN_MASK) button = 3;
+
+ int type = (button != 0) ?
+ MouseEvent.MOUSE_DRAGGED :MouseEvent.MOUSE_MOVED;
+
+ MouseEvent e = new MouseEvent(owner,
+ type,
+ System.currentTimeMillis(),
+ (modifiers & 0x2FF), x, y, clickCount,
+ false, button);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ protected void mousePressEvent( int modifiers, int x, int y, int clickCount)
+ {
+ if( (eventMask & AWTEvent.MOUSE_EVENT_MASK) == 0 )
+ return;
+ int button = 0;
+ if((modifiers & InputEvent.BUTTON1_DOWN_MASK) ==
+ InputEvent.BUTTON1_DOWN_MASK) button = 1;
+ if((modifiers & InputEvent.BUTTON2_DOWN_MASK) ==
+ InputEvent.BUTTON2_DOWN_MASK) button = 2;
+ if((modifiers & InputEvent.BUTTON3_DOWN_MASK) ==
+ InputEvent.BUTTON3_DOWN_MASK) button = 3;
+ MouseEvent e = new MouseEvent(owner,
+ MouseEvent.MOUSE_PRESSED,
+ System.currentTimeMillis(),
+ (modifiers & 0x2FF), x, y, clickCount,
+ ( button == POPUP_TRIGGER ),
+ button);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ protected void mouseReleaseEvent( int modifiers, int x, int y, int clickCount)
+ {
+ if( (eventMask & AWTEvent.MOUSE_EVENT_MASK) == 0 )
+ return;
+ int button = 0;
+ if((modifiers & InputEvent.BUTTON1_DOWN_MASK) ==
+ InputEvent.BUTTON1_DOWN_MASK) button = 1;
+ if((modifiers & InputEvent.BUTTON2_DOWN_MASK) ==
+ InputEvent.BUTTON2_DOWN_MASK) button = 2;
+ if((modifiers & InputEvent.BUTTON3_DOWN_MASK) ==
+ InputEvent.BUTTON3_DOWN_MASK) button = 3;
+
+ MouseEvent e = new MouseEvent(owner,
+ MouseEvent.MOUSE_RELEASED,
+ System.currentTimeMillis(),
+ (modifiers & 0x2FF), x, y, clickCount,
+ false, button);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ protected void moveEvent(int x, int y, int oldx, int oldy)
+ {
+ if( !ignoreResize )
+ {
+ // Since Component.setLocation calls back to setBounds,
+ // we need to ignore that.
+ ignoreResize = true;
+ owner.setLocation( x, y );
+ ignoreResize = false;
+ }
+ }
+
+ protected void resizeEvent(int oldWidth, int oldHeight,
+ int width, int height)
+ {
+ if(!(owner instanceof Window))
+ return;
+ updateBackBuffer(width, height);
+ ignoreResize = true;
+ owner.setSize(width, height);
+ ignoreResize = false;
+ ComponentEvent e = new ComponentEvent(owner,
+ ComponentEvent.COMPONENT_RESIZED);
+ QtToolkit.eventQueue.postEvent(e);
+ QtToolkit.repaintThread.queueComponent(this);
+ }
+
+ protected void showEvent()
+ {
+ if (owner instanceof Window)
+ {
+ WindowEvent e = new WindowEvent((Window)owner,
+ WindowEvent.WINDOW_OPENED);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+ else
+ {
+ ComponentEvent e = new ComponentEvent(owner,
+ ComponentEvent.COMPONENT_SHOWN);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+ }
+
+ protected void hideEvent()
+ {
+ ComponentEvent e = new ComponentEvent(owner,
+ ComponentEvent.COMPONENT_HIDDEN);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ // ************ Public methods *********************
+
+ /** Classpath-specific method */
+ public void setEventMask(long x)
+ {
+ eventMask = x;
+ }
+
+
+ public boolean canDetermineObscurity()
+ {
+ return true;
+ }
+
+ public int checkImage(Image img,
+ int w,
+ int h,
+ ImageObserver o)
+ {
+ return toolkit.checkImage(img, w, h, o);
+ }
+
+ public void createBuffers(int numBuffers, BufferCapabilities caps)
+ throws AWTException
+ {
+ // FIXME
+ }
+
+ public Image createImage(ImageProducer producer)
+ {
+ return toolkit.createImage(producer);
+ }
+
+ public Image createImage(int width, int height)
+ {
+ return new QtImage(width, height);
+ }
+
+ public void coalescePaintEvent(PaintEvent e)
+ {
+ // FIXME
+ }
+
+ public VolatileImage createVolatileImage(int w, int h)
+ {
+ return new QtVolatileImage( w, h );
+ }
+
+ public void destroyBuffers()
+ {
+ // FIXME
+ }
+
+ public void disable()
+ {
+ setEnabled(false);
+ }
+
+ public void dispose()
+ {
+ disposeNative();
+ if( backBuffer != null )
+ backBuffer.dispose();
+ }
+
+ public void enable()
+ {
+ setEnabled(true);
+ }
+
+ public void finalize()
+ {
+ dispose();
+ }
+
+ public void flip(BufferCapabilities.FlipContents contents)
+ {
+ }
+
+ public Image getBackBuffer()
+ {
+ return backBuffer;
+ }
+
+ public ColorModel getColorModel()
+ {
+ return toolkit.getColorModel();
+ }
+
+ public FontMetrics getFontMetrics(Font font)
+ {
+ return new QtFontMetrics( font, getGraphics() );
+ }
+
+ public Graphics getGraphics()
+ {
+ if( backBuffer == null )
+ {
+ Rectangle r = owner.getBounds();
+ backBuffer = new QtImage( r.width, r.height );
+ }
+ return backBuffer.getDirectGraphics( this );
+ }
+
+ public GraphicsConfiguration getGraphicsConfiguration()
+ {
+ int id = whichScreen(); // get the ID of the screen the widget is on.
+ GraphicsDevice[] devs = QtToolkit.graphicsEnv.getScreenDevices();
+ return devs[id].getDefaultConfiguration();
+ }
+
+ public Point getLocationOnScreen()
+ {
+ Point p = new Point();
+ synchronized( p )
+ {
+ getLocationOnScreenNative( p );
+ try
+ {
+ p.wait(); // Wait for the thing to be created.
+ }
+ catch(InterruptedException e)
+ {
+ }
+ }
+ return p;
+ }
+
+ private native void getSizeNative(Dimension d, boolean preferred);
+
+ private Dimension getSize(boolean preferred)
+ {
+ Dimension d = new Dimension();
+ synchronized( d )
+ {
+ getSizeNative(d, preferred);
+ try
+ {
+ d.wait(); // Wait for the thing to be created.
+ }
+ catch(InterruptedException e)
+ {
+ }
+ }
+ return d;
+ }
+
+ public Dimension getMinimumSize()
+ {
+ return getSize( false );
+ }
+
+ public Dimension getPreferredSize()
+ {
+ return getSize( true );
+ }
+
+ public Toolkit getToolkit()
+ {
+ return toolkit;
+ }
+
+ public native boolean handlesWheelScrolling();
+
+ public void hide()
+ {
+ setVisible(false);
+ }
+
+ public native boolean isFocusable();
+
+ public boolean isFocusTraversable()
+ {
+ // FIXME
+ return false;
+ }
+
+ public native boolean isObscured();
+
+ public Dimension minimumSize()
+ {
+ return getMinimumSize();
+ }
+
+ public Dimension preferredSize()
+ {
+ return getPreferredSize();
+ }
+
+ public native void requestFocus();
+
+ public boolean requestFocus (Component source, boolean bool1,
+ boolean bool2, long x)
+ {
+ // FIXME
+ return true;
+ }
+
+ public void reshape(int x,
+ int y,
+ int width,
+ int height)
+ {
+ setBounds( x, y, width, height );
+ }
+
+ public void setBackground(Color c)
+ {
+ if(c == null && !settingUp)
+ return;
+ setGround(c.getRed(), c.getGreen(), c.getBlue(), false);
+ }
+
+ public void setBounds(int x, int y, int width, int height)
+ {
+ if( ignoreResize )
+ return;
+ updateBackBuffer(width, height);
+ QtToolkit.repaintThread.queueComponent(this);
+ setBoundsNative(x, y, width, height);
+ }
+
+ public void setCursor(Cursor cursor)
+ {
+ if (cursor != null)
+ setCursor(cursor.getType());
+ }
+
+ public native void setEnabled(boolean b);
+
+ public void setFont(Font f)
+ {
+ if( f == null || f.getPeer() == null)
+ throw new IllegalArgumentException("Null font.");
+ setFontNative( (QtFontPeer)f.getPeer() );
+ }
+
+ public void setForeground(Color c)
+ {
+ if(c == null && !settingUp)
+ return;
+ setGround(c.getRed(), c.getGreen(), c.getBlue(), true);
+ }
+
+ public native void setVisible(boolean b);
+
+ public void show()
+ {
+ setVisible(true);
+ }
+
+ public void handleEvent (AWTEvent e)
+ {
+ int eventID = e.getID();
+ Rectangle r;
+
+ switch (eventID)
+ {
+ case ComponentEvent.COMPONENT_SHOWN:
+ QtToolkit.repaintThread.queueComponent(this);
+ break;
+ case PaintEvent.PAINT:
+ case PaintEvent.UPDATE:
+ r = ((PaintEvent)e).getUpdateRect();
+ QtToolkit.repaintThread.queueComponent(this, r.x, r.y,
+ r.width, r.height);
+ break;
+ case KeyEvent.KEY_PRESSED:
+ break;
+ case KeyEvent.KEY_RELEASED:
+ break;
+ }
+ }
+
+ /**
+ * paint() is called back from the native side in response to a native
+ * repaint event.
+ */
+ public void paint(Graphics g)
+ {
+ Rectangle r = g.getClipBounds();
+
+ if (backBuffer != null)
+ backBuffer.drawPixelsScaledFlipped ((QtGraphics) g,
+ 0, 0, 0, /* bg colors */
+ false, false, /* no flipping */
+ r.x, r.y, r.width, r.height,
+ r.x, r.y, r.width, r.height,
+ false ); /* no compositing */
+ }
+
+ public void paintBackBuffer() throws InterruptedException
+ {
+ if( backBuffer != null )
+ {
+ backBuffer.clear();
+ Graphics2D bbg = (Graphics2D)backBuffer.getGraphics();
+ owner.paint(bbg);
+ bbg.dispose();
+ }
+ }
+
+ public void paintBackBuffer(int x, int y, int w, int h)
+ throws InterruptedException
+ {
+ if( backBuffer != null )
+ {
+ Graphics2D bbg = (Graphics2D)backBuffer.getGraphics();
+ bbg.setBackground( getNativeBackground() );
+ bbg.clearRect(x, y, w, h);
+ bbg.setClip(x, y, w, h);
+ owner.paint(bbg);
+ bbg.dispose();
+ }
+ }
+
+ public boolean prepareImage(Image img,
+ int w,
+ int h,
+ ImageObserver o)
+ {
+ return toolkit.prepareImage(img, w, h, o);
+ }
+
+ public void print(Graphics g)
+ {
+ // FIXME
+ }
+
+ /**
+ * Schedules a timed repaint.
+ */
+ public void repaint(long tm,
+ int x,
+ int y,
+ int w,
+ int h)
+ {
+ if( tm <= 0 )
+ {
+ QtToolkit.repaintThread.queueComponent(this, x, y, w, h);
+ return;
+ }
+ Timer t = new Timer();
+ t.schedule(new RepaintTimerTask(this, x, y, w, h), tm);
+ }
+
+ /**
+ * Update the cursor (note that setCursor is usually not called)
+ */
+ public void updateCursorImmediately()
+ {
+ if (owner.getCursor() != null)
+ setCursor(owner.getCursor().getType());
+ }
+
+ /**
+ * Timed repainter
+ */
+ private class RepaintTimerTask extends TimerTask
+ {
+ private int x, y, w, h;
+ private QtComponentPeer peer;
+ RepaintTimerTask(QtComponentPeer peer, int x, int y, int w, int h)
+ {
+ this.x=x;
+ this.y=y;
+ this.w=w;
+ this.h=h;
+ this.peer=peer;
+ }
+ public void run()
+ {
+ QtToolkit.repaintThread.queueComponent(peer, x, y, w, h);
+ }
+ }
+
+ public native Rectangle getBounds();
+
+ public void reparent(ContainerPeer parent)
+ {
+ if(!(parent instanceof QtContainerPeer))
+ throw new IllegalArgumentException("Illegal peer.");
+ reparentNative((QtContainerPeer)parent);
+ }
+
+ public void setBounds(int x, int y, int width, int height, int z)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean isReparentSupported()
+ {
+ return true;
+ }
+
+ // What does this do, anyway?
+ public void layout()
+ {
+ // TODO Auto-generated method stub
+ }
+
+ public boolean requestFocus(Component lightweightChild, boolean temporary,
+ boolean focusedWindowChangeAllowed,
+ long time, sun.awt.CausedFocusEvent.Cause cause)
+ {
+ // TODO: Implement this properly and remove the other requestFocus()
+ // methods.
+ return true;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtContainerPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtContainerPeer.java
new file mode 100644
index 000000000..ee2873730
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtContainerPeer.java
@@ -0,0 +1,112 @@
+/* QtContainerPeer.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Component;
+import java.awt.Insets;
+import java.awt.peer.ContainerPeer;
+
+public class QtContainerPeer extends QtComponentPeer implements ContainerPeer
+{
+ public QtContainerPeer( QtToolkit kit, Component owner )
+ {
+ super( kit, owner );
+ }
+
+ protected void init()
+ {
+ }
+
+ protected void setup()
+ {
+ super.setup();
+ }
+
+ // ************ Public methods *********************
+ public void beginLayout()
+ {
+ // FIXME
+ }
+
+ public void beginValidate()
+ {
+ }
+
+ public void endLayout()
+ {
+ QtUpdate();
+ }
+
+ public void endValidate()
+ {
+ }
+
+ public Insets getInsets()
+ {
+ return new Insets(0, 0, 0, 0);
+ }
+
+ public Insets insets()
+ {
+ return getInsets();
+ }
+
+ public boolean isPaintPending()
+ {
+ // FIXME etc.
+ return false;
+ }
+
+ public boolean isRestackSupported()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void cancelPendingPaint(int x, int y, int width, int height)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void restack()
+ {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtDialogPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtDialogPeer.java
new file mode 100644
index 000000000..2f2c25550
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtDialogPeer.java
@@ -0,0 +1,73 @@
+/* QtDialogPeer.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Dialog;
+import java.awt.peer.DialogPeer;
+
+public class QtDialogPeer extends QtWindowPeer implements DialogPeer
+{
+ public QtDialogPeer( QtToolkit kit, Dialog owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ setTitle( ((Dialog)owner).getTitle() );
+ setResizable( ((Dialog)owner).isResizable() );
+ setModal( ((Dialog)owner).isModal() );
+ }
+
+ native void setModal(boolean modal);
+
+ private native void setBoundsNative(int x, int y, int width, int height, boolean fixed);
+
+ // ************ Public methods *********************
+
+ public native void setResizable (boolean resizeable);
+
+ public void setBounds(int x, int y, int width, int height)
+ {
+ setBoundsNative(x, y, width, height,
+ !((Dialog)owner).isResizable());
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtEmbeddedWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtEmbeddedWindowPeer.java
new file mode 100644
index 000000000..de76cd17f
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtEmbeddedWindowPeer.java
@@ -0,0 +1,64 @@
+/* QtEmbeddedWindowPeer.java -- embedded window peer
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Component;
+import gnu.java.awt.peer.EmbeddedWindowPeer;
+
+/**
+ * Embedded window peer for applets.
+ * FIXME: EmbeddedWindowPeer and this class should extend Window, NOT Frame.
+ */
+public class QtEmbeddedWindowPeer extends QtFramePeer implements EmbeddedWindowPeer
+{
+ public QtEmbeddedWindowPeer( QtToolkit kit, Component owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ }
+
+ // ************ Public methods *********************
+
+ public native void embed( long handle );
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtFileDialogPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtFileDialogPeer.java
new file mode 100644
index 000000000..06943d955
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtFileDialogPeer.java
@@ -0,0 +1,83 @@
+/* QtFileDialogPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.FileDialog;
+import java.io.FilenameFilter;
+import java.awt.peer.FileDialogPeer;
+
+public class QtFileDialogPeer extends QtDialogPeer implements FileDialogPeer
+{
+ public QtFileDialogPeer( QtToolkit kit, FileDialog owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ setMode( ((FileDialog)owner).getMode() );
+ }
+
+ /**
+ * Sets load or save mode
+ */
+ private native void setMode(int mode);
+
+ private void fileDialogDone(String path, String filename)
+ {
+ }
+
+ // ************ Public methods *********************
+ public void setFile (String file)
+ {
+ // FIXME
+ }
+
+ public void setDirectory (String dir)
+ {
+ // FIXME
+ }
+
+ public void setFilenameFilter (FilenameFilter ff)
+ {
+ // FIXME
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtFontMetrics.java b/libjava/classpath/gnu/java/awt/peer/qt/QtFontMetrics.java
new file mode 100644
index 000000000..1998339dc
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtFontMetrics.java
@@ -0,0 +1,125 @@
+/* QtFontMetrics.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.geom.Rectangle2D;
+
+public class QtFontMetrics extends FontMetrics
+{
+
+ private long nativeObject;
+ private QtFontPeer peer;
+
+ public QtFontMetrics( Font f )
+ {
+ super( f );
+ if(f.getPeer() == null || !(f.getPeer() instanceof QtFontPeer))
+ throw new IllegalArgumentException("Invalid Font object.");
+ peer = (QtFontPeer) f.getPeer();
+ init( peer );
+ }
+
+ public QtFontMetrics( Font f, Graphics g )
+ {
+ super( f );
+ if(f.getPeer() == null || !(f.getPeer() instanceof QtFontPeer))
+ throw new IllegalArgumentException("Invalid Font object.");
+ if( !(g instanceof QtGraphics) )
+ throw new IllegalArgumentException("Invalid graphics object.");
+ peer = (QtFontPeer) f.getPeer();
+ initGraphics(peer, (QtGraphics)g );
+ }
+
+ QtFontMetrics( QtFontPeer f, Graphics g )
+ {
+ super( null );
+ if( !(g instanceof QtGraphics) )
+ throw new IllegalArgumentException("Invalid graphics object.");
+ peer = f;
+ initGraphics(peer, (QtGraphics)g );
+ }
+
+ public QtFontMetrics( QtFontPeer fp )
+ {
+ super( (Font)null );
+ peer = fp;
+ init( peer );
+ }
+
+ private native void init(QtFontPeer fp);
+
+ private native void initGraphics(QtFontPeer fp, QtGraphics g);
+
+ private native void dispose();
+
+ native Rectangle2D getStringBounds(String s);
+
+ // ****************** Package private ***************************
+
+ native boolean canDisplay( int c );
+
+ // ****************** Public methods ****************************
+
+ public native int getAscent();
+
+ public native int getDescent();
+
+ public native int getHeight();
+
+ public native int getLeading();
+
+ public native int getMaxAdvance();
+
+ public native int charWidth(char c);
+
+ public int charsWidth(char[] chars, int off, int len)
+ {
+ return stringWidth( new String(chars, off, len) );
+ }
+
+ public native int stringWidth(String str);
+
+ public Rectangle2D getStringBounds(String str, Graphics context)
+ {
+ QtFontMetrics fm = new QtFontMetrics(peer, context);
+ return fm.getStringBounds( str );
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtFontPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtFontPeer.java
new file mode 100644
index 000000000..03ed1d2df
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtFontPeer.java
@@ -0,0 +1,197 @@
+/* QtFontPeer.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.geom.Rectangle2D;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.LineMetrics;
+import java.text.CharacterIterator;
+import java.util.Locale;
+import java.util.Map;
+
+import gnu.java.awt.peer.ClasspathFontPeer;
+
+public class QtFontPeer extends ClasspathFontPeer
+{
+ // Pointer to native QFont structure.
+ private long nativeObject;
+ private QtFontMetrics metrics;
+
+
+ public QtFontPeer (String name, int style)
+ {
+ this(name, style, 12);
+ }
+
+ public QtFontPeer (String name, int style, int size)
+ {
+ super(name, style, size);
+ init();
+ }
+
+ public QtFontPeer (String name, Map attributes)
+ {
+ super(name, attributes);
+ init();
+ }
+
+ public void init()
+ {
+ if(this.familyName == null)
+ throw new IllegalArgumentException("null family name");
+ if(this.familyName.equals("Helvetica"))
+ this.familyName = "sans serif";
+ if(this.familyName.equals("Dialog"))
+ this.familyName = "sans serif";
+ create(this.familyName, this.style, (int)this.size);
+ metrics = new QtFontMetrics(this);
+ }
+
+ /**
+ * Creates the QFont object.
+ */
+ private native void create(String name, int style, int size);
+
+ /**
+ * Destroys the QFont.
+ */
+ public native void dispose();
+
+
+ // ****************** ClasspathFontPeer Methods.
+
+ public boolean canDisplay (Font font, int c)
+ {
+ return metrics.canDisplay( c );
+ }
+
+ public int canDisplayUpTo (Font font, CharacterIterator i,
+ int start, int limit)
+ {
+ int index = start;
+ char c = i.setIndex( index );
+ while( index <= limit )
+ {
+ if(!canDisplay(font, c))
+ return index;
+ index++;
+ c = i.next();
+ }
+ return -1;
+ }
+
+ public String getSubFamilyName (Font font, Locale locale)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getPostScriptName (Font font)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getNumGlyphs (Font font)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getMissingGlyphCode (Font font)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public byte getBaselineFor (Font font, char c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getGlyphName (Font font, int glyphIndex)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public GlyphVector createGlyphVector (Font font,
+ FontRenderContext frc,
+ CharacterIterator ci)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public GlyphVector createGlyphVector (Font font,
+ FontRenderContext ctx,
+ int[] glyphCodes)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public GlyphVector layoutGlyphVector (Font font,
+ FontRenderContext frc,
+ char[] chars, int start,
+ int limit, int flags)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public FontMetrics getFontMetrics (Font font)
+ {
+ return new QtFontMetrics( this );
+ }
+
+ public boolean hasUniformLineMetrics (Font font)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public LineMetrics getLineMetrics (Font font,
+ CharacterIterator ci,
+ int begin, int limit,
+ FontRenderContext rc)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Rectangle2D getMaxCharBounds (Font font,
+ FontRenderContext rc)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtFramePeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtFramePeer.java
new file mode 100644
index 000000000..d5162106f
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtFramePeer.java
@@ -0,0 +1,164 @@
+/* QtFramePeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Component;
+import java.awt.Frame;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.MenuBar;
+import java.awt.Rectangle;
+import java.awt.peer.FramePeer;
+
+public class QtFramePeer extends QtWindowPeer implements FramePeer
+{
+ private int theState; // FIXME
+
+ long frameObject;
+
+ public QtFramePeer( QtToolkit kit, Component owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ setTitle( ((Frame)owner).getTitle() );
+ if( ((Frame)owner).getMenuBar() != null )
+ setMenuBar( ((Frame)owner).getMenuBar() );
+ }
+
+ private native void setIcon(QtImage image);
+
+ private native void setMaximizedBounds(int w, int h);
+
+ private native void setMenu(QtMenuBarPeer mb);
+
+ private native int menuBarHeight();
+
+ // ************ Public methods *********************
+
+ public void destroy()
+ {
+ dispose();
+ }
+
+ public int getState()
+ {
+ // FIXME
+ return theState;
+ }
+
+ public Insets getInsets()
+ {
+ int mbHeight = ( ((Frame)owner).getMenuBar() != null ) ?
+ menuBarHeight() : 0;
+ return new Insets(mbHeight, 0, 0, 0);
+ }
+
+ public void setIconImage(Image im)
+ {
+ if (im instanceof QtImage)
+ setIcon( (QtImage)im );
+ else
+ setIcon( new QtImage( im.getSource() ) );
+ }
+
+ public void setMaximizedBounds(Rectangle rect)
+ {
+ // FIXME
+ }
+
+ public void setMenuBar(MenuBar mb)
+ {
+ if( mb != null )
+ {
+ QtMenuBarPeer mbpeer = (QtMenuBarPeer)mb.getPeer();
+ if( mbpeer == null )
+ {
+ mb.addNotify();
+ mbpeer = (QtMenuBarPeer)mb.getPeer();
+ if( mbpeer == null )
+ throw new IllegalStateException("No menu bar peer.");
+ }
+ mbpeer.addMenus();
+ setMenu( mbpeer );
+ }
+ else
+ setMenu( null );
+ }
+
+ public void setResizable(boolean resizeable)
+ {
+ // FIXME
+ }
+
+ public void setState(int s)
+ {
+ theState = s;
+ // FIXME
+ }
+
+ 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;
+ }
+
+ public Rectangle getBoundsPrivate()
+ {
+ // TODO: Implement this properly.
+ throw new InternalError("Not yet implemented");
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtGraphics.java b/libjava/classpath/gnu/java/awt/peer/qt/QtGraphics.java
new file mode 100644
index 000000000..f68cc0dbd
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtGraphics.java
@@ -0,0 +1,714 @@
+/* QtGraphics.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.AlphaComposite;
+import java.awt.AWTPermission;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.GradientPaint;
+import java.awt.GraphicsConfiguration;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.RenderingHints;
+import java.awt.Rectangle;
+import java.awt.Paint;
+import java.awt.Polygon;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Arc2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Line2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ImageObserver;
+import java.awt.image.RenderedImage;
+import java.awt.image.renderable.RenderableImage;
+
+import java.text.AttributedCharacterIterator;
+import java.text.CharacterIterator;
+import java.util.Map;
+
+/**
+ * QtGraphics is an abstract implementation of Graphics2D over a QPainter
+ * object. This is to be subclassed for different drawing contexts,
+ * which may have different requirements.
+ */
+public abstract class QtGraphics extends Graphics2D
+{
+ /**
+ * Native QPainter pointer.
+ */
+ protected long nativeObject;
+
+ private static final AffineTransform identity = new AffineTransform();
+
+ // Graphics state
+ protected Font font; // Current font.
+ protected Color color, bgcolor; // Current color and background color.
+ protected Shape clip; // Current clipping area.
+ protected Shape initialClip; // Initial clip bounds
+ protected AffineTransform xform; // Current transform
+ protected Stroke currentStroke; // the current stroke
+ protected boolean nativeStroking; // whether we're using Qt's stroking or not
+ protected Composite composite; // current composite operator
+ protected double currentAlpha; // current alpha
+ protected Paint currentPaint; // current paint
+ protected RenderingHints renderingHints; // the rendering hints.
+
+ /**
+ * Owner Graphics, used by subcontext created by create()
+ * to avoid GC of the original context.
+ */
+ Graphics parent;
+
+ /**
+ * Do-nothing constructor.
+ */
+ QtGraphics()
+ {
+ }
+
+ /**
+ * Copying constructor - used by copy() and subclasses.
+ */
+ QtGraphics(QtGraphics parent)
+ {
+ cloneNativeContext( parent );
+ setFont( parent.getFont() );
+ setAlpha( parent.currentAlpha );
+ setBackground( parent.getBackground() );
+ setColor( parent.getColor() );
+ setClip( (initialClip = parent.getClip()) );
+ setTransform( parent.getTransform() );
+ setStroke( parent.getStroke() );
+ setComposite( parent.getComposite() );
+ setPaint( parent.getPaint() );
+ setRenderingHints( parent.getRenderingHints() );
+ }
+
+ /**
+ * Set up some generic defaults.
+ */
+ protected void setup()
+ {
+ font = new Font ("Dialog", Font.PLAIN, 12);
+ setTransform( identity );
+ setStroke( new BasicStroke() );
+ renderingHints = new RenderingHints( null );
+ }
+
+ public synchronized native void delete();
+
+ public void dispose()
+ {
+ }
+
+ // ********************** etc *******************************
+
+ private void resetClip()
+ {
+ AffineTransform current = getTransform();
+ setTransform( identity );
+ setClip( initialClip );
+ setTransform( current );
+ }
+
+ protected native void initImage(QtImage image);
+ protected native void initVolatileImage(QtVolatileImage image);
+
+ // Creates a new native QPainter object on the same context.
+ private native void cloneNativeContext( QtGraphics parent );
+ private native void setColor(int r, int g, int b, int a);
+ private native void drawNative( QPainterPath p );
+ private native void fillNative( QPainterPath p );
+ private native void setClipNative( QPainterPath p );
+ private native void setClipRectNative( int x, int y, int w, int h );
+ private native void intersectClipNative( QPainterPath p );
+ private native void intersectClipRectNative( int x, int y, int w, int h );
+ private native void setQtTransform(QMatrix m);
+ private native void setNativeStroke(QPen p);
+ private native void setNativeComposite(int alphaMode);
+ private native void drawStringNative(String string, double x, double y);
+ private native void setLinearGradient(int r1, int g1, int b1,
+ int r2, int g2, int b2,
+ double x1, double y1,
+ double x2, double y2, boolean cyclic);
+ private native void setAlphaNative(double alpha);
+ private native void setFontNative(QtFontPeer font);
+ private native QPainterPath getClipNative();
+
+ void setAlpha(double alpha)
+ {
+ currentAlpha = alpha;
+ setAlphaNative(currentAlpha);
+ }
+
+ // ************ Public methods *********************
+
+ /**
+ * Context-sensitive methods are declared abstract.
+ */
+ public abstract Graphics create();
+
+ public abstract void copyArea(int x, int y, int width, int height,
+ int dx, int dy);
+
+ public abstract GraphicsConfiguration getDeviceConfiguration();
+
+
+ public Color getColor()
+ {
+ return new Color(color.getRed(), color.getGreen(), color.getBlue());
+ }
+
+ public void setColor(Color c)
+ {
+ if( c == null )
+ c = Color.white;
+ this.color = c;
+ int alpha = (int)(c.getAlpha() * currentAlpha);
+ setColor(c.getRed(), c.getGreen(), c.getBlue(), alpha);
+ }
+
+ public void setBackground(Color color)
+ {
+ bgcolor = new Color(color.getRed(), color.getGreen(), color.getBlue());
+ }
+
+ public Color getBackground()
+ {
+ return new Color(bgcolor.getRed(), bgcolor.getGreen(), bgcolor.getBlue());
+ }
+
+ public void setPaintMode()
+ {
+ }
+
+ public void setXORMode(Color color)
+ {
+ // FIXME
+ }
+
+ public boolean hit(Rectangle rect, Shape s, boolean onStroke)
+ {
+ if( onStroke )
+ {
+ Shape stroked = currentStroke.createStrokedShape( s );
+ return stroked.intersects( (double)rect.x, (double)rect.y,
+ (double)rect.width, (double)rect.height );
+ }
+ return s.intersects( (double)rect.x, (double)rect.y,
+ (double)rect.width, (double)rect.height );
+ }
+
+ // ******************* Font ***********************
+ public Font getFont()
+ {
+ return font;
+ }
+
+ public void setFont(Font font)
+ {
+ if( font == null )
+ return;
+ this.font = font;
+ if(font.getPeer() != null && font.getPeer() instanceof QtFontPeer)
+ setFontNative( (QtFontPeer)font.getPeer() );
+ }
+
+ public FontMetrics getFontMetrics(Font font)
+ {
+ return new QtFontMetrics(font, this);
+ }
+
+ // ***************** Clipping *********************
+
+ /**
+ * Intersects the current clip with the shape
+ */
+ public void clip(Shape s)
+ {
+ intersectClipNative( new QPainterPath( s ) );
+ }
+
+ public void clipRect(int x, int y, int width, int height)
+ {
+ intersectClipRectNative( x, y, width, height );
+ }
+
+ public void setClip(int x, int y, int width, int height)
+ {
+ setClipRectNative( x, y, width, height );
+ }
+
+ public Shape getClip()
+ {
+ return getClipNative().getPath();
+ }
+
+ public native Rectangle getClipBounds();
+
+ /**
+ * Sets the clip
+ */
+ public void setClip(Shape clip)
+ {
+ if (clip == null)
+ resetClip();
+ else
+ setClipNative(new QPainterPath( clip ));
+ }
+
+ // ***************** Drawing primitives *********************
+
+ public void draw(Shape s)
+ {
+ if( nativeStroking )
+ drawNative( new QPainterPath(s) );
+ else
+ fillNative( new QPainterPath( currentStroke.createStrokedShape( s ) ) );
+ }
+
+ public void fill(Shape s)
+ {
+ fillNative( new QPainterPath(s) );
+ }
+
+ public void drawLine(int x1, int y1, int x2, int y2)
+ {
+ if( nativeStroking )
+ drawNative( new QPainterPath((double)x1, (double)y1, (double)x2, (double)y2, true) );
+ else
+ draw( new Line2D.Double((double)x1, (double)y1, (double)x2, (double)y2) );
+ }
+
+ public void drawRect(int x, int y, int width, int height)
+ {
+ if( nativeStroking )
+ drawNative( new QPainterPath((double)x, (double)y,
+ (double)width, (double)height) );
+ else
+ fillNative( new QPainterPath
+ ( currentStroke.createStrokedShape
+ (new Rectangle2D.Double
+ ((double)x, (double)y,
+ (double)width, (double)height) ) ) );
+ }
+
+ public void fillRect(int x, int y, int width, int height)
+ {
+ fillNative( new QPainterPath( x, y, width, height ) );
+ }
+
+ public void clearRect(int x, int y, int width, int height)
+ {
+ Color c = color;
+ setColor( bgcolor ); // FIXME
+ fillRect( x, y, width, height );
+ setColor( c );
+ }
+
+ public void drawRoundRect(int x, int y, int width, int height,
+ int arcWidth, int arcHeight)
+ {
+ draw( new RoundRectangle2D.Double(x, y, width, height,
+ arcWidth, arcHeight) );
+ }
+
+ public void fillRoundRect(int x, int y, int width, int height,
+ int arcWidth, int arcHeight)
+ {
+ fill( new RoundRectangle2D.Double(x, y, width, height,
+ arcWidth, arcHeight) );
+ }
+
+ public void drawOval(int x, int y, int width, int height)
+ {
+ draw( new Ellipse2D.Double((double)x, (double)y,
+ (double)width, (double)height) );
+ }
+
+ public void fillOval(int x, int y, int width, int height)
+ {
+ fill( new Ellipse2D.Double(x, y, width, height) );
+ }
+
+ public void drawArc(int x, int y, int width, int height,
+ int arcStart, int arcAngle)
+ {
+ draw( new Arc2D.Double(x, y, width, height, arcStart, arcAngle,
+ Arc2D.OPEN) );
+ }
+
+ public void fillArc(int x, int y, int width, int height,
+ int arcStart, int arcAngle)
+ {
+ fill( new Arc2D.Double(x, y, width, height, arcStart, arcAngle,
+ Arc2D.CHORD) );
+ }
+
+ public void drawPolyline(int xPoints[], int yPoints[], int npoints)
+ {
+ for( int i = 0; i < npoints - 1; i++)
+ drawLine(xPoints[i], yPoints[i], xPoints[i + 1], yPoints[i + 1]);
+ }
+
+ public void drawPolygon(int xPoints[], int yPoints[], int npoints)
+ {
+ draw( new Polygon(xPoints, yPoints, npoints) );
+ }
+
+ public void fillPolygon(int xPoints[], int yPoints[], int npoints)
+ {
+ fill( new Polygon(xPoints, yPoints, npoints) );
+ }
+
+ public native void fill3DRect(int x, int y, int width, int height, boolean raised);
+
+ public native void draw3DRect(int x, int y, int width, int height, boolean raised);
+
+ // *********************** Text rendering *************************
+
+ public void drawString(String string, int x, int y)
+ {
+ drawStringNative(string, (double)x, (double)y);
+ }
+
+ public void drawString(String string, float x, float y)
+ {
+ drawStringNative(string, (double)x, (double)y);
+ }
+
+ public void drawString (AttributedCharacterIterator ci, int x, int y)
+ {
+ // FIXME - to something more correct ?
+ String s = "";
+ for(char c = ci.first(); c != CharacterIterator.DONE; c = ci.next())
+ s += c;
+ drawString(s, x, y);
+ }
+
+ public void drawString(AttributedCharacterIterator ci,
+ float x, float y)
+ {
+ // FIXME - to something more correct ?
+ String s = "";
+ for(char c = ci.first(); c != CharacterIterator.DONE; c = ci.next())
+ s += c;
+ drawString(s, x, y);
+ }
+
+ public void drawGlyphVector(GlyphVector v, float x, float y)
+ {
+ throw new RuntimeException("Not implemented");
+ }
+
+ // ******************* Image drawing ******************************
+ public boolean drawImage(Image image,
+ AffineTransform Tx,
+ ImageObserver obs)
+ {
+ if (image instanceof QtImage)
+ return ((QtImage)image).drawImage(this, new QMatrix( Tx ), obs);
+
+ return (new QtImage(image.getSource())).drawImage(this,
+ new QMatrix( Tx ),
+ obs);
+ }
+
+ public boolean drawImage(Image image, int x, int y, Color bgcolor,
+ ImageObserver observer)
+ {
+ if (image instanceof QtImage)
+ return ((QtImage)image).drawImage (this, x, y, bgcolor, observer);
+ return (new QtImage(image.getSource())).drawImage (this, x, y,
+ bgcolor, observer);
+ }
+
+ public boolean drawImage(Image image,
+ int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ Color bgcolor, ImageObserver observer)
+ {
+ if (image instanceof QtImage)
+ return ((QtImage)image).drawImage(this, dx1, dy1, dx2, dy2,
+ sx1, sy1, sx2, sy2, bgcolor, observer);
+
+ return (new QtImage(image.getSource())).drawImage(this, dx1, dy1,
+ dx2, dy2,
+ sx1, sy1, sx2, sy2,
+ bgcolor, observer);
+ }
+
+ public boolean drawImage(Image image, int x, int y,
+ int width, int height, Color bgcolor,
+ ImageObserver observer)
+ {
+ if (image instanceof QtImage)
+ return ((QtImage)image).drawImage (this, x, y, width, height,
+ bgcolor, observer);
+ return (new QtImage(image.getSource())).drawImage (this, x, y,
+ width, height,
+ bgcolor, observer);
+ }
+
+ public boolean drawImage(Image image, int x, int y, int width, int height,
+ ImageObserver observer)
+ {
+ return drawImage(image, x, y, width, height, null, observer);
+ }
+
+ public boolean drawImage(Image image, int x, int y, ImageObserver observer)
+ {
+ return drawImage(image, x, y, null, observer);
+ }
+
+ public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer)
+ {
+ return drawImage(image, dx1, dy1, dx2, dy2,
+ sx1, sy1, sx2, sy2, null, observer);
+ }
+
+ // *********************** Transform methods *************************
+ public AffineTransform getTransform()
+ {
+ return new AffineTransform( xform );
+ }
+
+ public void setTransform(AffineTransform Tx)
+ {
+ xform = new AffineTransform( Tx );
+ setQtTransform( new QMatrix( xform ) );
+ }
+
+ public void rotate(double theta)
+ {
+ xform.rotate( theta );
+ setQtTransform( new QMatrix( xform ) );
+ }
+
+ public void rotate(double theta, double x, double y)
+ {
+ xform.rotate(theta, x, y);
+ setQtTransform( new QMatrix( xform ) );
+ }
+
+ public void scale(double sx, double sy)
+ {
+ xform.scale(sx, sy);
+ setQtTransform( new QMatrix( xform ) );
+ }
+
+ public void shear(double shx, double shy)
+ {
+ xform.shear(shx, shy);
+ setQtTransform( new QMatrix( xform ) );
+ }
+
+ public void transform(AffineTransform Tx)
+ {
+ xform.concatenate( Tx );
+ setQtTransform( new QMatrix( xform ) );
+ }
+
+ public void translate(double tx, double ty)
+ {
+ xform.translate( tx, ty );
+ setQtTransform( new QMatrix( xform ) );
+ }
+
+ public void translate(int x, int y)
+ {
+ translate((double)x, (double)y);
+ }
+
+ // *************** Stroking, Filling, Compositing *****************
+ public void setStroke(Stroke s)
+ {
+ try // ..to convert the stroke into a native one.
+ {
+ QPen pen = new QPen( s );
+ nativeStroking = true;
+ setNativeStroke( pen );
+ setColor( color );
+ }
+ catch (IllegalArgumentException e)
+ {
+ nativeStroking = false;
+ }
+ currentStroke = s;
+ }
+
+ public Stroke getStroke()
+ { // FIXME: return copy?
+ return currentStroke;
+ }
+
+ public void setComposite(Composite comp)
+ {
+ if( comp == null)
+ {
+ setNativeComposite( AlphaComposite.SRC_OVER );
+ return;
+ }
+
+ if( comp instanceof AlphaComposite )
+ {
+ if( ((AlphaComposite)comp).getRule() != AlphaComposite.XOR )
+ setAlpha( ((AlphaComposite)comp).getAlpha() );
+ setNativeComposite( ((AlphaComposite)comp).getRule() );
+ composite = comp;
+ }
+ else
+ {
+ // FIXME: this check is only required "if this Graphics2D
+ // context is drawing to a Component on the display screen".
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new AWTPermission("readDisplayPixels"));
+
+ throw new UnsupportedOperationException("We don't support custom"+
+ " composites yet.");
+ }
+ }
+
+ public Composite getComposite()
+ {
+ return composite;
+ }
+
+ public void setPaint(Paint p)
+ {
+ if( p == null )
+ return;
+
+ // FIXME
+ currentPaint = p;
+ if( p instanceof GradientPaint )
+ {
+ GradientPaint lg = (GradientPaint)p;
+ setLinearGradient(lg.getColor1().getRed(), lg.getColor1().getGreen(),
+ lg.getColor1().getBlue(), lg.getColor2().getRed(),
+ lg.getColor2().getGreen(), lg.getColor2().getBlue(),
+ lg.getPoint1().getX(), lg.getPoint1().getY(),
+ lg.getPoint2().getX(), lg.getPoint2().getY(),
+ lg.isCyclic() );
+ return;
+ }
+ if( p instanceof Color )
+ {
+ setColor((Color) p);
+ return;
+ }
+ throw new UnsupportedOperationException("We don't support custom"+
+ " paints yet.");
+ }
+
+ public Paint getPaint()
+ {
+ // FIXME
+ return currentPaint;
+ }
+
+ // ********************** Rendering Hints *************************
+
+ public void addRenderingHints(Map hints)
+ {
+ renderingHints.putAll( hints );
+ }
+
+ public Object getRenderingHint(RenderingHints.Key hintKey)
+ {
+ return renderingHints.get( hintKey );
+ }
+
+ public RenderingHints getRenderingHints()
+ {
+ return (RenderingHints) renderingHints.clone();
+ }
+
+ public void setRenderingHints(Map<?,?> hints)
+ {
+ renderingHints = new RenderingHints( null );
+ renderingHints.putAll(hints);
+ updateRenderingHints();
+ }
+
+ public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue)
+ {
+ renderingHints.put( hintKey, hintValue );
+ updateRenderingHints();
+ }
+
+ private void updateRenderingHints()
+ {
+ // FIXME - update native settings.
+ }
+
+ ////////////////////////////// unimplemented /////////////////////
+
+ public FontRenderContext getFontRenderContext()
+ {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ public void drawRenderableImage(RenderableImage image, AffineTransform xform)
+ {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ public void drawRenderedImage(RenderedImage image, AffineTransform xform)
+ {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y)
+ {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtGraphicsEnvironment.java b/libjava/classpath/gnu/java/awt/peer/qt/QtGraphicsEnvironment.java
new file mode 100644
index 000000000..dec4db2c8
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtGraphicsEnvironment.java
@@ -0,0 +1,105 @@
+/* QtGraphicsEnvironment.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.image.BufferedImage;
+import java.util.Locale;
+
+public class QtGraphicsEnvironment extends GraphicsEnvironment
+{
+ QtToolkit toolkit;
+ GraphicsDevice[] screens;
+
+ public QtGraphicsEnvironment (QtToolkit tk)
+ {
+ super();
+ toolkit = tk;
+ // Get the number of screens from Qt.
+ int n = toolkit.numScreens();
+
+ /**
+ * Create the screen device objects
+ */
+ screens = new GraphicsDevice[ n ];
+ for(int i = 0; i < n; i++)
+ screens[ i ] = new QtScreenDevice( i );
+ }
+
+ public Font[] getAllFonts ()
+ {
+ String[] fonts = getAvailableFontFamilyNames();
+ Font[] fontObjs = new Font[fonts.length];
+ for( int i = 0; i < fonts.length; i++)
+ fontObjs[i] = new Font(fonts[i], Font.PLAIN, 12);
+ return fontObjs;
+ }
+
+ public String[] getAvailableFontFamilyNames()
+ {
+ return toolkit.getFontList();
+ }
+
+ public String[] getAvailableFontFamilyNames(Locale l)
+ {
+ return getAvailableFontFamilyNames();
+ }
+
+ public GraphicsDevice getDefaultScreenDevice ()
+ {
+ return screens[ toolkit.defaultScreen() ];
+ }
+
+ public Graphics2D createGraphics (BufferedImage image)
+ {
+ return (Graphics2D)image.getGraphics();
+ }
+
+ public GraphicsDevice[] getScreenDevices()
+ {
+ return screens;
+ }
+
+ public QtToolkit getToolkit()
+ {
+ return toolkit;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtImage.java b/libjava/classpath/gnu/java/awt/peer/qt/QtImage.java
new file mode 100644
index 000000000..b7e50ea25
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtImage.java
@@ -0,0 +1,641 @@
+/* QtImage.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Graphics;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.MemoryImageSource;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.io.File;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import java.io.BufferedInputStream;
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.WeakHashMap;
+import java.util.Vector;
+
+/**
+ * QtImage - wraps a QImage
+ *
+ */
+public class QtImage extends Image
+{
+ int width = -1, height = -1;
+
+ /**
+ * Properties.
+ */
+ Hashtable props;
+
+ /**
+ * Loaded or not flag, for asynchronous compatibility.
+ */
+ boolean isLoaded;
+
+ /**
+ * Pointer to the QImage
+ */
+ long nativeObject;
+
+ /**
+ * Observer queue.
+ */
+ Vector observers;
+
+ /**
+ * Error flag for loading.
+ */
+ boolean errorLoading;
+
+ /**
+ * Original source, if created from an ImageProducer.
+ */
+ ImageProducer source;
+
+ /*
+ * The 32-bit AARRGGBB format the uses.
+ */
+ static ColorModel nativeModel = new DirectColorModel(32,
+ 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF,
+ 0xFF000000);
+ /**
+ * HashMap of Graphics objects painting on this Image.
+ */
+ WeakHashMap painters;
+
+ /**
+ * Flags if this image is to be destroyed.
+ */
+ boolean killFlag;
+
+ /**
+ * Clears the image to RGBA 0
+ */
+ public native void clear();
+
+ /**
+ * Returns a copy of the pixel data as a java array.
+ */
+ private native int[] getPixels();
+
+ /**
+ * Sets the pixel data from a java array.
+ */
+ private native void setPixels(int[] pixels);
+
+ /**
+ * Loads an image
+ */
+ private native boolean loadImage(String name);
+
+ /**
+ * Loads an image from data.
+ */
+ private native boolean loadImageFromData(byte[] data);
+
+ /**
+ * Allocates a QImage
+ */
+ private native void createImage();
+
+ /**
+ * Frees the above.
+ */
+ private synchronized native void freeImage();
+
+ /**
+ * Sets the image to scaled copy of src image. hints are rendering hints.
+ */
+ private native void createScaledImage(QtImage src, int hints);
+
+ /**
+ * Draws the image optionally composited.
+ */
+ native void drawPixels (QtGraphics gc,
+ int bg_red, int bg_green, int bg_blue,
+ int x, int y,
+ boolean composite);
+ /**
+ * Draws the image, optionally scaled and composited.
+ */
+ private native void drawPixelsScaled (QtGraphics gc,
+ int bg_red, int bg_green, int bg_blue,
+ int x, int y, int width, int height,
+ boolean composite);
+
+ /**
+ * Draws the image transformed.
+ */
+ private native void drawPixelsTransformed (QtGraphics gc, QMatrix transform);
+
+ /**
+ * Draws the image scaled flipped and optionally composited.
+ */
+ native void drawPixelsScaledFlipped (QtGraphics gc,
+ int bg_red, int bg_green,
+ int bg_blue,
+ boolean flipX, boolean flipY,
+ int srcX, int srcY,
+ int srcWidth, int srcHeight,
+ int dstX, int dstY,
+ int dstWidth, int dstHeight,
+ boolean composite);
+
+ /**
+ * Creates the image from an ImageProducer. May result in an error image.
+ */
+ public QtImage (ImageProducer producer)
+ {
+ killFlag = false;
+ isLoaded = false;
+ observers = new Vector();
+ source = producer;
+ errorLoading = false;
+ if( producer != null )
+ source.startProduction(new QtImageConsumer(this, source));
+ }
+
+ /**
+ * Creates the image from a URL. May result in an error image.
+ */
+ public QtImage (URL url)
+ {
+ killFlag = false;
+ 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 a QtImage by loading a given file.
+ *
+ * @throws IllegalArgumentException if the image could not be loaded.
+ */
+ public QtImage (String filename)
+ {
+ killFlag = false;
+ File f = new File(filename);
+ observers = null;
+ props = new Hashtable();
+ try
+ {
+ String fn = f.getCanonicalPath();
+ if (loadImage( fn ) != true)
+ {
+ errorLoading = true;
+ isLoaded = false;
+ return;
+ }
+ }
+ catch(IOException e)
+ {
+ errorLoading = true;
+ isLoaded = false;
+ return;
+ }
+ errorLoading = false;
+ isLoaded = true;
+ }
+
+ /**
+ * Constructs a QtImage from a byte array of an image file.
+ *
+ * @throws IllegalArgumentException if the image could not be loaded.
+ */
+ public QtImage (byte[] data)
+ {
+ if (loadImageFromData(data) != true)
+ throw new IllegalArgumentException("Couldn't load image.");
+
+ killFlag = false;
+ isLoaded = true;
+ observers = null;
+ errorLoading = false;
+ props = new Hashtable();
+ }
+
+ /**
+ * Constructs an empty QtImage.
+ */
+ public QtImage (int width, int height)
+ {
+ this.width = width;
+ this.height = height;
+ props = new Hashtable();
+ isLoaded = true;
+ killFlag = false;
+ observers = null;
+ errorLoading = false;
+ createImage();
+ clear();
+ }
+
+ /**
+ * Constructs a scaled version of the src bitmap, using Qt
+ */
+ private QtImage (QtImage src, int width, int height, int hints)
+ {
+ this.width = width;
+ this.height = height;
+ props = new Hashtable();
+ isLoaded = true;
+ killFlag = false;
+ observers = null;
+ errorLoading = false;
+
+ createScaledImage(src, hints);
+ }
+
+ /**
+ * Callback from the image consumer.
+ */
+ public void setImage(int width, int height,
+ int[] pixels, Hashtable properties)
+ {
+ this.width = width;
+ this.height = height;
+ props = (properties != null) ? properties : new Hashtable();
+
+ if (width <= 0 || height <= 0 || pixels == null)
+ {
+ errorLoading = true;
+ return;
+ }
+
+ isLoaded = true;
+ deliver();
+ createImage();
+ setPixels(pixels);
+ }
+
+ // java.awt.Image methods ////////////////////////////////////////////////
+
+ public int getWidth (ImageObserver observer)
+ {
+ if (addObserver(observer))
+ return -1;
+
+ return width;
+ }
+
+ public int getHeight (ImageObserver observer)
+ {
+ if (addObserver(observer))
+ return -1;
+
+ return height;
+ }
+
+ public Object getProperty (String name, ImageObserver observer)
+ {
+ if (addObserver(observer))
+ return UndefinedProperty;
+
+ Object value = props.get (name);
+ return (value == null) ? UndefinedProperty : value;
+ }
+
+ /**
+ * Returns the source of this image.
+ */
+ public ImageProducer getSource ()
+ {
+ if (!isLoaded)
+ return null;
+ return new MemoryImageSource(width, height, nativeModel, getPixels(),
+ 0, width);
+ }
+
+ void putPainter(QtImageGraphics g)
+ {
+ if( painters == null )
+ painters = new WeakHashMap();
+ painters.put( g, "dummy" );
+ }
+
+ void removePainter(QtImageGraphics g)
+ {
+ painters.remove( g );
+ if( killFlag && painters.isEmpty() )
+ freeImage();
+ }
+
+ /**
+ * Creates a Graphics context for this image.
+ */
+ public Graphics getGraphics ()
+ {
+ if (!isLoaded || killFlag)
+ return null;
+
+ return new QtImageGraphics(this);
+ }
+
+ /**
+ * Creates a Graphics context for this image.
+ */
+ Graphics getDirectGraphics(QtComponentPeer peer)
+ {
+ if (!isLoaded)
+ return null;
+
+ return new QtImageDirectGraphics(this, peer);
+ }
+
+ /**
+ * Returns a scaled instance of this image.
+ */
+ public Image getScaledInstance(int width,
+ int height,
+ int hints)
+ {
+ if (width <= 0 || height <= 0)
+ throw new IllegalArgumentException("Width and height of scaled bitmap"+
+ "must be >= 0");
+
+ return new QtImage(this, width, height, hints);
+ }
+
+ /**
+ * If the image is loaded and comes from an ImageProducer,
+ * regenerate the image from there.
+ *
+ * I have no idea if this is ever actually used. Since QtImage can't be
+ * instantiated directly, how is the user to know if it was created from
+ * an ImageProducer or not?
+ */
+ public synchronized void flush ()
+ {
+ if (isLoaded && source != null)
+ {
+ observers = new Vector();
+ isLoaded = false;
+ freeImage();
+ source.startProduction(new QtImageConsumer(this, source));
+ }
+ }
+
+ public void finalize()
+ {
+ dispose();
+ }
+
+ public void dispose()
+ {
+ if (isLoaded)
+ {
+ if( painters == null || painters.isEmpty() )
+ freeImage();
+ else
+ killFlag = true; // can't destroy image yet.
+ // Do so when all painters are gone.
+ }
+ }
+
+ /**
+ * Returns the image status, used by QtToolkit
+ */
+ public int checkImage (ImageObserver observer)
+ {
+ if (addObserver(observer))
+ {
+ if (errorLoading == true)
+ return ImageObserver.ERROR;
+ else
+ return 0;
+ }
+
+ return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT;
+ }
+
+ // Drawing methods ////////////////////////////////////////////////
+
+ /**
+ * Draws an image with eventual scaling/transforming.
+ */
+ public boolean drawImage (QtGraphics g, QMatrix matrix,
+ ImageObserver observer)
+ {
+ if (addObserver(observer))
+ return false;
+
+ drawPixelsTransformed (g, matrix);
+
+ return true;
+ }
+
+ /**
+ * Draws an image to the QtGraphics context, at (x,y) with optional
+ * compositing with a background color.
+ */
+ public boolean drawImage (QtGraphics g, int x, int y,
+ Color bgcolor, ImageObserver observer)
+ {
+ if (addObserver(observer))
+ return false;
+
+ if(bgcolor != null)
+ drawPixels(g, bgcolor.getRed (), bgcolor.getGreen (),
+ bgcolor.getBlue (), x, y, true);
+ else
+ drawPixels(g, 0, 0, 0, x, y, false);
+
+ return true;
+ }
+
+ /**
+ * Draws an image to the QtGraphics context, at (x,y) scaled to
+ * width and height, with optional compositing with a background color.
+ */
+ public boolean drawImage (QtGraphics g, int x, int y, int width, int height,
+ Color bgcolor, ImageObserver observer)
+ {
+ if (addObserver(observer))
+ return false;
+
+ if(bgcolor != null)
+ drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (),
+ bgcolor.getBlue (), x, y, width, height, true);
+ else
+ drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false);
+
+ return true;
+ }
+
+ /**
+ * Draws an image with eventual scaling/transforming.
+ */
+ public boolean drawImage (QtGraphics g, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ Color bgcolor, ImageObserver observer)
+ {
+ if (addObserver(observer))
+ return false;
+
+ boolean flipX = (dx1 > dx2)^(sx1 > sx2);
+ boolean flipY = (dy1 > dy2)^(sy1 > sy2);
+ int dstWidth = Math.abs (dx2 - dx1);
+ int dstHeight = Math.abs (dy2 - dy1);
+ int srcWidth = Math.abs (sx2 - sx1);
+ int srcHeight = Math.abs (sy2 - sy1);
+ int srcX = (sx1 < sx2) ? sx1 : sx2;
+ int srcY = (sy1 < sy2) ? sy1 : sy2;
+ int dstX = (dx1 < dx2) ? dx1 : dx2;
+ int dstY = (dy1 < dy2) ? dy1 : dy2;
+
+ // Clipping. This requires the dst to be scaled as well,
+ if (srcWidth > width)
+ {
+ dstWidth = (int)((double)dstWidth*((double)width/(double)srcWidth));
+ srcWidth = width - srcX;
+ }
+
+ if (srcHeight > height)
+ {
+ dstHeight = (int)((double)dstHeight*((double)height/(double)srcHeight));
+ srcHeight = height - srcY;
+ }
+
+ if (srcWidth + srcX > width)
+ {
+ dstWidth = (int)((double)dstWidth * (double)(width - srcX)/(double)srcWidth);
+ srcWidth = width - srcX;
+ }
+
+ if (srcHeight + srcY > height)
+ {
+ dstHeight = (int)((double)dstHeight * (double)(width - srcY)/(double)srcHeight);
+ srcHeight = height - srcY;
+ }
+
+ if ( srcWidth <= 0 || srcHeight <= 0 || dstWidth <= 0 || dstHeight <= 0)
+ return true;
+
+ if(bgcolor != null)
+ drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (),
+ bgcolor.getBlue (),
+ flipX, flipY,
+ srcX, srcY,
+ srcWidth, srcHeight,
+ dstX, dstY,
+ dstWidth, dstHeight,
+ true);
+ else
+ drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY,
+ srcX, srcY, srcWidth, srcHeight,
+ dstX, dstY, dstWidth, dstHeight,
+ false);
+ return true;
+ }
+
+ public native void copyArea(int x, int y, int width, int height,
+ int dx, int dy);
+
+ // Private methods ////////////////////////////////////////////////
+
+ /**
+ * Delivers notifications to all queued observers.
+ */
+ private void deliver()
+ {
+ int flags = ImageObserver.HEIGHT |
+ ImageObserver.WIDTH |
+ ImageObserver.PROPERTIES |
+ ImageObserver.ALLBITS;
+
+ if (observers != null)
+ for(int i=0; i < observers.size(); i++)
+ ((ImageObserver)observers.elementAt(i)).
+ imageUpdate(this, flags, 0, 0, width, height);
+
+ observers = null;
+ }
+
+ /**
+ * Adds an observer, if we need to.
+ * @return true if an observer was added.
+ */
+ private boolean addObserver(ImageObserver observer)
+ {
+ if (!isLoaded)
+ {
+ if(observer != null)
+ if (!observers.contains (observer))
+ observers.addElement (observer);
+ return true;
+ }
+ return false;
+ }
+
+ public String toString()
+ {
+ return "QtImage [isLoaded="+isLoaded+", width="+width+", height="+height
+ +"]";
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtImageConsumer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtImageConsumer.java
new file mode 100644
index 000000000..9883475f9
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtImageConsumer.java
@@ -0,0 +1,147 @@
+/* QtImageConsumer.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.image.ColorModel;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ImageProducer;
+import java.util.Hashtable;
+
+/**
+ * Helper class to QtImage. Sits and gathers pixels for a QtImage and then
+ * calls QtImage.setImage().
+ *
+ * @author Sven de Marothy
+ */
+public class QtImageConsumer implements ImageConsumer
+{
+ private QtImage target;
+ private int width, height;
+ private Hashtable properties;
+ private int[] pixelCache = null;
+ private ImageProducer source;
+
+ public QtImageConsumer(QtImage target, ImageProducer source)
+ {
+ this.target = target;
+ this.source = source;
+ }
+
+ public synchronized void imageComplete (int status)
+ {
+ source.removeConsumer(this);
+ target.setImage(width, height, pixelCache, properties);
+ }
+
+ public synchronized void setColorModel (ColorModel model)
+ {
+ // This method is to inform on what the most used color model
+ // in the image is, for optimization reasons. We ignore this
+ // information.
+ }
+
+ public synchronized void setDimensions (int width, int height)
+ {
+ pixelCache = new int[width*height];
+
+ this.width = width;
+ this.height = height;
+ }
+
+ public synchronized void setHints (int flags)
+ {
+ // This method informs us in which order the pixels are
+ // delivered, for progressive-loading support, etc.
+ // Since we wait until it's all loaded, we can ignore the hints.
+ }
+
+ public synchronized void setPixels (int x, int y, int width, int height,
+ ColorModel cm, byte[] pixels,
+ int offset, int scansize)
+ {
+ setPixels (x, y, width, height, cm, convertPixels (pixels), offset,
+ scansize);
+ }
+
+ public synchronized void setPixels (int x, int y, int width, int height,
+ ColorModel cm, int[] pixels,
+ int offset, int scansize)
+ {
+ if (pixelCache == null)
+ return; // Not sure this should ever happen.
+
+ if (cm.equals(QtImage.nativeModel))
+ for (int i = 0; i < height; i++)
+ System.arraycopy (pixels, offset + (i * scansize),
+ pixelCache, (y + i) * this.width + x,
+ width);
+ else
+ {
+ for (int i = 0; i < height; i++)
+ for (int j = 0; j < width; j++)
+ {
+ // get in AARRGGBB and convert to AABBGGRR
+ int pix = cm.getRGB(pixels[offset + (i * scansize) + x + j]);
+ byte b = (byte)(pix & 0xFF);
+ byte r = (byte)(((pix & 0x00FF0000) >> 16) & 0xFF);
+ pix &= 0xFF00FF00;
+ pix |= ((b & 0xFF) << 16);
+ pix |= (r & 0xFF);
+ pixelCache[(y + i) * this.width + x + j] = pix;
+ }
+ }
+ }
+
+ /**
+ * This is an old method, no idea if it's correct.
+ */
+ private int[] convertPixels (byte[] pixels)
+ {
+ int ret[] = new int[pixels.length];
+
+ for (int i = 0; i < pixels.length; i++)
+ ret[i] = pixels[i] & 0xFF;
+
+ return ret;
+ }
+
+ public synchronized void setProperties (Hashtable props)
+ {
+ this.properties = props;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtImageDirectGraphics.java b/libjava/classpath/gnu/java/awt/peer/qt/QtImageDirectGraphics.java
new file mode 100644
index 000000000..daa174ad4
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtImageDirectGraphics.java
@@ -0,0 +1,145 @@
+/* QtImageDirectGraphics.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.image.ImageObserver;
+
+/**
+ * A QtImagePainter that does an update after every drawing op.
+ */
+public class QtImageDirectGraphics extends QtImageGraphics
+{
+ private QtComponentPeer peer;
+ private boolean modified;
+
+ public QtImageDirectGraphics(QtImage image, QtComponentPeer peer)
+ {
+ super( image );
+ this.peer = peer;
+ modified = false;
+ }
+
+ public QtImageDirectGraphics(QtImageGraphics g)
+ {
+ super( g );
+ }
+
+ private void scheduleUpdate()
+ {
+ }
+
+ public void dispose()
+ {
+ super.dispose();
+ peer.toolkit.sync();
+ peer.QtUpdate();
+ }
+
+ public void draw(Shape s)
+ {
+ super.draw(s);
+ scheduleUpdate();
+ }
+
+ public void fill(Shape s)
+ {
+ super.fill(s);
+ scheduleUpdate();
+ }
+
+ public void drawString(String string, int x, int y)
+ {
+ super.drawString( string, x, y );
+ scheduleUpdate();
+ }
+
+ public void drawString(String string, float x, float y)
+ {
+ super.drawString( string, x, y );
+ scheduleUpdate();
+ }
+
+ public void drawLine(int x1, int y1, int x2, int y2)
+ {
+ super.drawLine(x1, y1, x2, y2);
+ scheduleUpdate();
+ }
+
+ public boolean drawImage(Image image,
+ AffineTransform Tx,
+ ImageObserver obs)
+ {
+ boolean r = super.drawImage(image, Tx, obs);
+ scheduleUpdate();
+ return r;
+ }
+
+ public boolean drawImage(Image image, int x, int y, Color bgcolor,
+ ImageObserver observer)
+ {
+ boolean r = super.drawImage(image, x, y, bgcolor, observer);
+ scheduleUpdate();
+ return r;
+ }
+
+ public boolean drawImage(Image image,
+ int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ Color bgcolor, ImageObserver observer)
+ {
+ boolean r = super.drawImage( image, dx1, dy1, dx2, dy2,
+ sx1, sy1, sx2, sy2,
+ bgcolor, observer);
+ scheduleUpdate();
+ return r;
+ }
+
+ public boolean drawImage(Image image, int x, int y,
+ int width, int height, Color bgcolor,
+ ImageObserver observer)
+ {
+ boolean r = super.drawImage(image, x, y, width, height, bgcolor,
+ observer);
+ scheduleUpdate();
+ return r;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtImageGraphics.java b/libjava/classpath/gnu/java/awt/peer/qt/QtImageGraphics.java
new file mode 100644
index 000000000..bba25e068
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtImageGraphics.java
@@ -0,0 +1,139 @@
+/* QtImageGraphics.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Color;
+import java.awt.GraphicsConfiguration;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.util.Stack;
+
+/**
+ * QtComponentPainter is a Graphics2D context for painting to QtImage and
+ * QtVolatileImages.
+ */
+public class QtImageGraphics extends QtGraphics
+{
+ Image parentImage;
+ Stack owners;
+ QtImageGraphics topParent;
+
+ public QtImageGraphics(Image image)
+ {
+ if(!( image instanceof QtVolatileImage || image instanceof QtImage))
+ throw new IllegalArgumentException("Cannot create QtImageGraphics for a non-QImage context.");
+
+ owners = new Stack();
+ owners.push(this);
+ topParent = null;
+ int w, h;
+ if(image instanceof QtImage)
+ {
+ w = ((QtImage)image).width;
+ h = ((QtImage)image).height;
+ initImage((QtImage) image );
+ ((QtImage)image).putPainter( this );
+ }
+ else
+ {
+ w = ((QtVolatileImage)image).width;
+ h = ((QtVolatileImage)image).height;
+ initVolatileImage((QtVolatileImage) image );
+ ((QtVolatileImage)image).putPainter( this );
+ }
+
+ parentImage = image;
+ initialClip = new Rectangle( 0, 0, w, h );
+ setClip( initialClip );
+ setBackground(Color.white); // fixme
+ currentAlpha = 1.0;
+ setColor(Color.black);
+ setup();
+ }
+
+ /**
+ * Copying constructor
+ */
+ QtImageGraphics( QtImageGraphics g )
+ {
+ super( g );
+ parentImage = g.parentImage;
+ if(parentImage instanceof QtImage)
+ ((QtImage)parentImage).putPainter( this );
+ else
+ ((QtVolatileImage)parentImage).putPainter( this );
+ }
+
+ public void dispose()
+ {
+ delete();
+ if( parentImage instanceof QtImage )
+ ((QtImage)parentImage).removePainter( this );
+ else
+ ((QtVolatileImage)parentImage).removePainter( this );
+ }
+
+ /**
+ * Create a copy of this context.
+ */
+ public Graphics create()
+ {
+ return new QtImageGraphics( this );
+ }
+
+ /**
+ * Copy an area.
+ */
+ public void copyArea(int x, int y, int width, int height,
+ int dx, int dy)
+ {
+ if(parentImage instanceof QtImage)
+ ((QtImage)parentImage).copyArea(x, y, width, height, dx, dy);
+ else
+ ((QtVolatileImage)parentImage).copyArea(x, y, width, height, dx, dy);
+ }
+
+ /**
+ * Returns the GraphicsConfiguration of the context component.
+ */
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtLabelPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtLabelPeer.java
new file mode 100644
index 000000000..80acd491d
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtLabelPeer.java
@@ -0,0 +1,62 @@
+/* QtLabelPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Label;
+import java.awt.peer.LabelPeer;
+
+public class QtLabelPeer extends QtComponentPeer implements LabelPeer
+{
+ public QtLabelPeer( QtToolkit kit, Label owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ setText( ((Label)owner).getText() );
+ setAlignment( ((Label)owner).getAlignment() );
+ }
+
+ public native void setAlignment( int alignment );
+
+ public native void setText( String label );
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtListPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtListPeer.java
new file mode 100644
index 000000000..14ae2a0cd
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtListPeer.java
@@ -0,0 +1,188 @@
+/* QtListPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Dimension;
+import java.awt.List;
+import java.awt.event.ActionEvent;
+import java.awt.event.ItemEvent;
+import java.awt.peer.ListPeer;
+
+public class QtListPeer extends QtComponentPeer implements ListPeer
+{
+ public QtListPeer( QtToolkit kit, List owner )
+ {
+ super( kit, owner );
+ }
+
+ public native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ List o = (List)owner;
+ // Multiple selection
+ setMultipleMode(o.isMultipleMode());
+ // Add initial list items.
+ String[] items = o.getItems();
+ for (int i = 0; i < items.length; i++)
+ add(items[i], i);
+
+ // Initial selections.
+ int[] selected = o.getSelectedIndexes();
+ for (int i = 0; i < selected.length; i++)
+ select(selected[i]);
+
+ // If no initial selection, use 0.
+ if(selected.length == 0 && items.length > 0)
+ select( 0 );
+ }
+
+ private boolean ignoreNextSelect = false;
+
+ /**
+ * Called back when a row is selected. -1 if no row is selected.
+ */
+ private void fireChoice( int index )
+ {
+ ignoreNextSelect = true;
+ if( index == -1)
+ ((List)owner).deselect( ((List)owner).getSelectedIndex() );
+ else
+ {
+ ((List)owner).select( index );
+ ItemEvent e = new ItemEvent((List)owner,
+ ItemEvent.ITEM_STATE_CHANGED,
+ ""+index,
+ ItemEvent.SELECTED);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+ }
+
+ /**
+ * Called back when an item is double-clicked.
+ */
+ private void itemDoubleClicked( int index, int modifiers )
+ {
+ ActionEvent e = new ActionEvent(owner,
+ ActionEvent.ACTION_PERFORMED,
+ ((List)owner).getItem( index ),
+ System.currentTimeMillis(),
+ modifiers);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ private native void select(int index, boolean selected);
+
+ // ************ Public methods *********************
+
+ public native void add(String item, int index);
+
+ public void addItem(String item, int index)
+ {
+ add(item, index);
+ }
+
+ public void clear()
+ {
+ removeAll();
+ }
+
+ /**
+ * Deletes items from the starting index to the ending index (inclusive).
+ */
+ public native void delItems(int start_index, int end_index);
+
+ public void deselect(int index)
+ {
+ if( ignoreNextSelect == true )
+ ignoreNextSelect = false;
+ else
+ select(index, false);
+ }
+
+ public native int[] getSelectedIndexes();
+
+ public native void makeVisible(int index);
+
+ public Dimension minimumSize(int s)
+ {
+ return getMinimumSize(s);
+ }
+
+ public Dimension preferredSize(int s)
+ {
+ return getPreferredSize(s);
+ }
+
+ public void removeAll()
+ {
+ delItems(0, ((List)owner).getItemCount() - 1);
+ }
+
+ public void select(int index)
+ {
+ if( ignoreNextSelect == true )
+ ignoreNextSelect = false;
+ else
+ select(index, true);
+ }
+
+ /**
+ * Sets multiple-selection mode.
+ * Note there's a bug in multiple selection in Qt 4.0.0, use 4.0.1.
+ */
+ public native void setMultipleMode(boolean multi);
+
+ public void setMultipleSelections(boolean multi)
+ {
+ setMultipleMode(multi);
+ }
+
+ public Dimension getPreferredSize(int s)
+ {
+ // FIXME
+ return getPreferredSize();
+ }
+
+ public Dimension getMinimumSize(int s)
+ {
+ // FIXME
+ return getMinimumSize();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtMenuBarPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtMenuBarPeer.java
new file mode 100644
index 000000000..962d76d41
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtMenuBarPeer.java
@@ -0,0 +1,101 @@
+/* QtMenuBarPeer.java -- Qt peer for a menu bar.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.peer.MenuBarPeer;
+
+public class QtMenuBarPeer extends QtMenuComponentPeer implements MenuBarPeer
+{
+ public QtMenuBarPeer( QtToolkit kit, MenuBar owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ }
+
+ /**
+ * Recurses the menubar adding menus (and menu items),
+ * called from the Frame peer.
+ */
+ void addMenus()
+ {
+ MenuBar o = (MenuBar)owner;
+ int help = (o.getHelpMenu() != null) ? 1 : 0;
+ for (int i = 0; i < o.getMenuCount() - help; i++)
+ addMenu( o.getMenu(i) );
+ if(o.getHelpMenu() != null)
+ addHelpMenu( o.getHelpMenu() );
+ }
+
+ private native void addMenu( QtMenuPeer mp );
+
+ private native void addHelpMenu( QtMenuPeer mp );
+
+ private native void delMenu( QtMenuPeer mp );
+
+ // ************ Public methods *********************
+
+ public void addMenu( Menu m )
+ {
+ if (m.getPeer() == null)
+ m.addNotify();
+ ((QtMenuPeer)m.getPeer()).addItems();
+ addMenu( (QtMenuPeer)m.getPeer() );
+ }
+
+ public void addHelpMenu( Menu m )
+ {
+ if (m.getPeer() == null)
+ m.addNotify();
+ ((QtMenuPeer)m.getPeer()).addItems();
+ addHelpMenu( (QtMenuPeer)m.getPeer() );
+ }
+
+ public void delMenu( int index )
+ {
+ Menu m = ((MenuBar)owner).getMenu( index );
+ if(m != null)
+ delMenu( (QtMenuPeer)m.getPeer() );
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtMenuComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtMenuComponentPeer.java
new file mode 100644
index 000000000..2050bef06
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtMenuComponentPeer.java
@@ -0,0 +1,94 @@
+/* QtMenuComponentPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Font;
+import java.awt.MenuComponent;
+import java.awt.peer.MenuComponentPeer;
+
+public class QtMenuComponentPeer extends NativeWrapper
+ implements MenuComponentPeer
+{
+ protected QtToolkit toolkit;
+ protected MenuComponent owner;
+
+ public QtMenuComponentPeer( QtToolkit kit, MenuComponent owner )
+ {
+ this.toolkit = kit;
+ this.owner = owner;
+ nativeObject = 0;
+ synchronized(this)
+ {
+ callInit(); // Calls the init method FROM THE MAIN THREAD.
+ try
+ {
+ wait(); // Wait for the thing to be created.
+ }
+ catch(InterruptedException e)
+ {
+ }
+ }
+ setup();
+ }
+
+ protected native void callInit();
+
+ protected void init()
+ {
+ }
+
+ protected void setup()
+ {
+ }
+
+ public void finalize()
+ {
+ dispose();
+ }
+
+ // ************ Public methods *********************
+
+ public native void dispose();
+
+ public void setFont(Font font)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtMenuItemPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtMenuItemPeer.java
new file mode 100644
index 000000000..2b77540a5
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtMenuItemPeer.java
@@ -0,0 +1,100 @@
+/* QtMenuItemPeer.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.MenuItem;
+import java.awt.CheckboxMenuItem;
+import java.awt.event.ActionEvent;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.CheckboxMenuItemPeer;
+
+public class QtMenuItemPeer extends QtMenuComponentPeer
+ implements MenuItemPeer, CheckboxMenuItemPeer
+{
+ public QtMenuItemPeer( QtToolkit toolkit, MenuItem owner )
+ {
+ super(toolkit, owner);
+ }
+
+ protected void init()
+ {
+ String label = ((MenuItem)owner).getLabel();
+ create(label, label.equals("-"), (owner instanceof CheckboxMenuItem));
+ }
+
+ protected void setup()
+ {
+ }
+
+ private native void create(String label, boolean isSeperator, boolean isCheckable);
+
+ public void finalize()
+ {
+ dispose();
+ }
+
+ public native void dispose();
+
+ private void fireClick(int modifiers)
+ {
+ ActionEvent e = new ActionEvent(owner,
+ ActionEvent.ACTION_PERFORMED,
+ ((MenuItem)owner).getActionCommand(),
+ System.currentTimeMillis(),
+ (modifiers & 0x2FF));
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ // ************ Public methods *********************
+
+ public void disable()
+ {
+ setEnabled(false);
+ }
+
+ public void enable()
+ {
+ setEnabled(true);
+ }
+
+ public native void setEnabled(boolean b);
+
+ public native void setLabel(String label);
+
+ public native void setState(boolean state);
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtMenuPeer.java
new file mode 100644
index 000000000..0f65fecbd
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtMenuPeer.java
@@ -0,0 +1,149 @@
+/* QtMenuPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Menu;
+import java.awt.MenuItem;
+import java.awt.PopupMenu;
+import java.awt.event.ActionEvent;
+import java.awt.peer.MenuPeer;
+import java.util.Vector;
+
+public class QtMenuPeer extends QtMenuComponentPeer implements MenuPeer
+{
+ Vector items;
+ boolean itemsAdded;
+
+ public QtMenuPeer( QtToolkit kit, Menu owner )
+ {
+ super( kit, owner );
+ itemsAdded = false;
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ items = new Vector();
+ setLabel( ((Menu)owner).getLabel() );
+ if( ((Menu)owner).isTearOff() )
+ allowTearOff();
+ }
+
+ // Recurse the menu tree adding items,
+ // called from the MenuBar addMenus() method, called from the Frame peer.
+ void addItems()
+ {
+ if(!itemsAdded)
+ {
+ Menu o = (Menu)owner;
+ for( int i=0; i < o.getItemCount(); i++ )
+ {
+ MenuItem ci = o.getItem(i);
+ if (ci instanceof Menu && ci.getPeer() != null)
+ ((QtMenuPeer)ci.getPeer()).addItems();
+ addItem( ci );
+ }
+ itemsAdded = true;
+ }
+ }
+
+ private void fireClick()
+ {
+ ActionEvent e = new ActionEvent(owner,
+ ActionEvent.ACTION_PERFORMED,
+ ((Menu)owner).getActionCommand());
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ private native void allowTearOff();
+
+ private native void insertSeperator();
+
+ private native void insertItem(QtMenuItemPeer p);
+
+ private native void insertMenu(QtMenuPeer menu);
+
+ private native void delItem(long ptr);
+
+ private void add(long ptr)
+ {
+ items.add(new Long(ptr));
+ }
+
+ // ************ Public methods *********************
+
+ public void addItem( MenuItem item )
+ {
+ if( item instanceof Menu || item instanceof PopupMenu)
+ insertMenu((QtMenuPeer)item.getPeer());
+ else
+ {
+ QtMenuItemPeer p = (QtMenuItemPeer)item.getPeer();
+ insertItem(p);
+ }
+ }
+
+ public void addSeparator()
+ {
+ insertSeperator();
+ }
+
+ public void delItem( int index )
+ {
+ long ptr = ((Long)items.elementAt(index)).longValue();
+ delItem(ptr);
+ items.removeElementAt(index);
+ }
+
+ // Inherited methods..
+
+ public void disable()
+ {
+ setEnabled(false);
+ }
+
+ public void enable()
+ {
+ setEnabled(true);
+ }
+
+ public native void setEnabled(boolean enabled);
+
+ public native void setLabel(String text);
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtPanelPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtPanelPeer.java
new file mode 100644
index 000000000..1ac0ca9a6
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtPanelPeer.java
@@ -0,0 +1,56 @@
+/* QtPanelPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Component;
+import java.awt.peer.PanelPeer;
+
+public class QtPanelPeer extends QtContainerPeer implements PanelPeer
+{
+ public QtPanelPeer( QtToolkit kit, Component owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtPopupMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtPopupMenuPeer.java
new file mode 100644
index 000000000..eb4dae404
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtPopupMenuPeer.java
@@ -0,0 +1,76 @@
+/* QtPopupMenuPeer.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.PopupMenu;
+import java.awt.Event;
+import java.awt.peer.PopupMenuPeer;
+
+public class QtPopupMenuPeer extends QtMenuPeer implements PopupMenuPeer
+{
+ public QtPopupMenuPeer( QtToolkit kit, PopupMenu owner )
+ {
+ super( kit, owner );
+ }
+
+ private native void showNative(int x, int y);
+
+ // ************ Public methods *********************
+
+ /**
+ * Part of the older API, replaced by event version instead.
+ */
+ public void show (Component origin, int x, int y)
+ {
+ if( origin == null )
+ throw new NullPointerException("Null parent component.");
+ addItems();
+
+ Point p = origin.getLocationOnScreen();
+ showNative( (int)p.getX() + x, (int)p.getY() + y );
+ }
+
+ public void show (Event e)
+ {
+ if (!(e.target instanceof Component))
+ throw new IllegalArgumentException("Expecting a component Event target!");
+ show((Component)e.target, e.x, e.y);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtRepaintThread.java b/libjava/classpath/gnu/java/awt/peer/qt/QtRepaintThread.java
new file mode 100644
index 000000000..6861be8fc
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtRepaintThread.java
@@ -0,0 +1,156 @@
+/* QtRepaintThread.java -- Repaint thread implementation
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+/**
+ * This class does repainting of Component back-buffers. It is undesirable to
+ * do this directly from the paint callback in QtComponentPeer, because that
+ * is executed from the main thread. Thus, if a call is made at the same time
+ * which requires execution by the main thread, and this is sharing a lock with
+ * paint(), then a deadlock will occur, which must be avoided. In general,
+ * the main Qt thread should avoid calling into java code as far as possible.
+ *
+ */
+public class QtRepaintThread extends Thread
+{
+ static class RepaintComponent
+ {
+ public QtComponentPeer curr;
+ public RepaintComponent next;
+ public boolean paintAll;
+ public int x, y, w, h;
+
+ public RepaintComponent(QtComponentPeer p)
+ {
+ curr = p;
+ next = null;
+ paintAll = true;
+ }
+
+ public RepaintComponent(QtComponentPeer p, int x, int y, int w, int h)
+ {
+ this(p);
+ paintAll = false;
+ this.x = x;
+ this.y = y;
+ this.w = w;
+ this.h = h;
+ }
+ }
+
+ RepaintComponent component;
+ boolean busy;
+
+ public QtRepaintThread()
+ {
+ component = null;
+ }
+
+ public void run()
+ {
+ while( true )
+ {
+ try
+ {
+ busy = false;
+ // Wait for a repaint
+ sleep(100);
+ busy = true;
+ }
+ catch (InterruptedException ie)
+ {
+ while( component != null )
+ {
+ try
+ {
+ if( component.paintAll )
+ {
+ // update the back-buffer.
+ component.curr.paintBackBuffer();
+ component.curr.QtUpdate(); // trigger a native repaint event
+ }
+ else
+ {
+ component.curr.paintBackBuffer(component.x, component.y,
+ component.w, component.h);
+ component.curr.QtUpdateArea(component.x, component.y,
+ component.w, component.h);
+ }
+ }
+ catch (InterruptedException e)
+ {
+ }
+ component = component.next;
+ }
+ }
+ }
+ }
+
+ /**
+ * Enqueue a component for repainting.
+ */
+ public synchronized void queueComponent(QtComponentPeer p)
+ {
+ if( component == null )
+ component = new RepaintComponent(p);
+ else
+ {
+ RepaintComponent r = component;
+ while( r.next != null ) r = r.next;
+ r.next = new RepaintComponent(p);
+ }
+ interrupt();
+ }
+
+ /**
+ * Enqueue a component for repainting.
+ */
+ public synchronized void queueComponent(QtComponentPeer p, int x, int y,
+ int w, int h)
+ {
+ if( component == null )
+ component = new RepaintComponent(p, x, y, w, h);
+ else
+ {
+ RepaintComponent r = component;
+ while( r.next != null ) r = r.next;
+ r.next = new RepaintComponent(p, x, y, w, h);
+ }
+ interrupt();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtScreenDevice.java b/libjava/classpath/gnu/java/awt/peer/qt/QtScreenDevice.java
new file mode 100644
index 000000000..c7d8a4784
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtScreenDevice.java
@@ -0,0 +1,115 @@
+/* QtScreenDevice.java -- Wrapper on a Qt screen Widget
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.DisplayMode;
+import java.awt.GraphicsConfigTemplate;
+import java.awt.Rectangle;
+import java.awt.Window;
+
+public class QtScreenDevice extends GraphicsDevice
+{
+ private long nativeObject;
+ private int id;
+ private String IDstring;
+ QtScreenDeviceConfiguration config;
+
+ public QtScreenDevice(int id)
+ {
+ this.id = id;
+ IDstring = "QtScreen" + id;
+ init( id );
+ config = new QtScreenDeviceConfiguration(this);
+ }
+
+ public native void init( int id );
+ public native void dispose();
+
+ // Package-private methods used by QtScreenDeviceConfiguration
+ native Rectangle getBounds();
+ native int getDpiX();
+ native int getDpiY();
+ native int depth();
+
+ // ****************** Public methods ***********************
+
+ public GraphicsConfiguration getBestConfiguration(GraphicsConfigTemplate gct)
+ {
+ return config;
+ }
+
+ public GraphicsConfiguration[] getConfigurations()
+ {
+ return new GraphicsConfiguration[]{ config };
+ }
+
+ public GraphicsConfiguration getDefaultConfiguration()
+ {
+ return config;
+ }
+
+ public String getIDstring()
+ {
+ return IDstring;
+ }
+
+ public int getType()
+ {
+ return TYPE_RASTER_SCREEN;
+ }
+
+ public boolean isDisplayChangeSupported()
+ {
+ return false;
+ }
+
+ public boolean isFullScreenSupported()
+ {
+ return false;
+ }
+
+ public void setDisplayMode(DisplayMode dm)
+ {
+ }
+
+ public void setFullScreenWindow(Window w)
+ {
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtScreenDeviceConfiguration.java b/libjava/classpath/gnu/java/awt/peer/qt/QtScreenDeviceConfiguration.java
new file mode 100644
index 000000000..34de36c09
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtScreenDeviceConfiguration.java
@@ -0,0 +1,145 @@
+/* QtScreenDeviceConfiguration.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.ImageCapabilities;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.VolatileImage;
+import java.awt.geom.AffineTransform;
+
+public class QtScreenDeviceConfiguration extends GraphicsConfiguration {
+
+ private QtScreenDevice owner;
+ private Rectangle bounds;
+ private double dpiX, dpiY;
+ private int depth;
+
+ public QtScreenDeviceConfiguration(QtScreenDevice owner)
+ {
+ this.owner = owner;
+ bounds = owner.getBounds();
+ dpiX = owner.getDpiX();
+ dpiY = owner.getDpiY();
+ depth = owner.depth();
+ }
+
+ public BufferedImage createCompatibleImage(int width, int height)
+ {
+ switch( depth )
+ {
+ case 24:
+ return new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
+ case 16:
+ return new BufferedImage(width, height,
+ BufferedImage.TYPE_USHORT_565_RGB);
+ case 8:
+ return new BufferedImage(width, height, BufferedImage.TYPE_BYTE_INDEXED);
+ default:
+ case 32:
+ return new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ }
+ }
+
+ public BufferedImage createCompatibleImage(int width, int height, int transparency)
+ {
+ // FIXME: Take the transpareny flag into account?
+ // For now, ignore it and just use an alpha channel.
+ if(depth == 32)
+ return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ return createCompatibleImage(width, height);
+ }
+
+ public VolatileImage createCompatibleVolatileImage(int width, int height)
+ {
+ return new QtVolatileImage( width, height );
+ }
+
+ public VolatileImage createCompatibleVolatileImage(int width, int height,
+ ImageCapabilities caps)
+ {
+ return createCompatibleVolatileImage( width, height );
+ }
+
+ public Rectangle getBounds()
+ {
+ return bounds;
+ }
+
+ public ColorModel getColorModel()
+ {
+ // FIXME?
+ return QtToolkit.getDefaultToolkit().getColorModel();
+ }
+
+ public ColorModel getColorModel(int transparency)
+ {
+ // FIXME?
+ return QtToolkit.getDefaultToolkit().getColorModel();
+ }
+
+ public AffineTransform getDefaultTransform()
+ {
+ return new AffineTransform();
+ }
+
+ public GraphicsDevice getDevice()
+ {
+ return owner;
+ }
+
+ /**
+ * Returns the transform which transforms from this display's resolution
+ * to a 72 DPI resolution.
+ */
+ public AffineTransform getNormalizingTransform()
+ {
+ AffineTransform nTrans = new AffineTransform();
+ nTrans.scale( 72.0 / dpiX, 72.0 / dpiY );
+ return nTrans;
+ }
+
+ public VolatileImage createCompatibleVolatileImage(int width, int height,
+ int transparency)
+ {
+ return createCompatibleVolatileImage(width, height);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtScrollPanePeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtScrollPanePeer.java
new file mode 100644
index 000000000..079d06de7
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtScrollPanePeer.java
@@ -0,0 +1,90 @@
+/* QtScrollPanePeer.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Adjustable;
+import java.awt.Insets;
+import java.awt.ScrollPane;
+import java.awt.peer.ScrollPanePeer;
+
+public class QtScrollPanePeer extends QtContainerPeer implements ScrollPanePeer
+{
+ public QtScrollPanePeer( QtToolkit kit, ScrollPane owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ setPolicy( ((ScrollPane)owner).getScrollbarDisplayPolicy() );
+ }
+
+ private native void setPolicy(int policy);
+
+ // ************ Public methods *********************
+
+ public native void childResized(int width, int height);
+
+ public native int getHScrollbarHeight();
+
+ public native int getVScrollbarWidth();
+
+ public native void setScrollPosition(int x, int y);
+
+ public Insets getInsets()
+ {
+ // FIXME : more accurate?
+ return new Insets(5 + getHScrollbarHeight(), // Top
+ 5 + getVScrollbarWidth(), // Left
+ 5, // Bottom
+ 5); // Right
+ }
+
+ public void setUnitIncrement(Adjustable item, int inc)
+ {
+ // FIXME
+ }
+
+ public void setValue(Adjustable item, int value)
+ {
+ // FIXME
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtScrollbarPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtScrollbarPeer.java
new file mode 100644
index 000000000..694287131
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtScrollbarPeer.java
@@ -0,0 +1,80 @@
+/* QtScrollbarPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Scrollbar;
+import java.awt.event.AdjustmentEvent;
+import java.awt.peer.ScrollbarPeer;
+
+public class QtScrollbarPeer extends QtComponentPeer implements ScrollbarPeer
+{
+ public QtScrollbarPeer( QtToolkit kit, Scrollbar owner )
+ {
+ super( kit, owner );
+ }
+
+ public native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ Scrollbar o = (Scrollbar)owner;
+ setValues(o.getValue(), o.getVisible(), o.getMinimum(), o.getMaximum());
+ setOrientation(o.getOrientation());
+ setLineIncrement(o.getLineIncrement());
+ setPageIncrement(o.getPageIncrement());
+ }
+
+ private native void setOrientation(int orientation);
+
+ private void fireMoved(int type, int value)
+ {
+ AdjustmentEvent e = new AdjustmentEvent((Scrollbar)owner,
+ AdjustmentEvent.ADJUSTMENT_VALUE_CHANGED,
+ type, value);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ // ************ Public methods *********************
+
+ public native void setLineIncrement(int inc);
+
+ public native void setPageIncrement(int inc);
+
+ public native void setValues(int value, int visible, int min, int max);
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtTextAreaPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtTextAreaPeer.java
new file mode 100644
index 000000000..a5aff58ef
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtTextAreaPeer.java
@@ -0,0 +1,179 @@
+/* QtTextAreaPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.TextArea;
+import java.awt.event.TextEvent;
+import java.awt.im.InputMethodRequests;
+import java.awt.peer.TextAreaPeer;
+
+public class QtTextAreaPeer extends QtComponentPeer implements TextAreaPeer
+{
+ public QtTextAreaPeer( QtToolkit kit, TextArea owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ setText(((TextArea)owner).getText());
+ setEditable(((TextArea)owner).isEditable());
+ }
+
+ /**
+ * Returns the start (start = true) or end (start = false) of the selection.
+ */
+ private native int getSelection(boolean start);
+
+ /**
+ * Called back on a text edit.
+ */
+ private void textChanged()
+ {
+ TextEvent e = new TextEvent(owner, TextEvent.TEXT_VALUE_CHANGED);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ // ************ Public methods *********************
+
+ public long filterEvents(long filter)
+ {
+ return filter;
+ }
+
+ public native int getCaretPosition();
+
+ public Rectangle getCharacterBounds(int pos)
+ {
+ // FIXME
+ return new Rectangle(0,0,0,0);
+ }
+
+ /**
+ * Implemented, but who uses it?
+ */
+ public native int getIndexAtPoint(int x, int y);
+
+// public void reshape(int x, int y,
+// int width, int height)
+// {
+// if(width != 0 || height != 0)
+// super.reshape(x, y, width, height);
+// else
+// super.reshape(x, y, 10, 10);
+// }
+
+ public Dimension getMinimumSize(int rows, int cols)
+ {
+ // FIXME
+ return getMinimumSize();
+ }
+
+ public Dimension getPreferredSize(int rows, int cols)
+ {
+ // FIXME
+ return getPreferredSize();
+ }
+
+ public int getSelectionEnd()
+ {
+ return getSelection(false);
+ }
+
+ public int getSelectionStart()
+ {
+ return getSelection(true);
+ }
+
+ public native String getText();
+
+ public void insert(String text, int pos)
+ {
+ // Not very efficient, no.
+ String s = getText();
+ setText(s.substring(0, pos) + text + s.substring(pos));
+ }
+
+ public void insertText(String text, int pos)
+ {
+ insert(text, pos);
+ }
+
+ public Dimension minimumSize(int rows, int cols)
+ {
+ return getMinimumSize(rows, cols);
+ }
+
+ public Dimension preferredSize(int rows, int cols)
+ {
+ return getPreferredSize(rows, cols);
+ }
+
+ public void replaceRange(String insert, int start_pos, int end_pos)
+ {
+ // Not very efficient, no.
+ String text = getText();
+ String right = text.substring(0, start_pos);
+ String left = text.substring(end_pos);
+ setText(right + insert + left);
+ }
+
+ public void replaceText(String text, int start_pos, int end_pos)
+ {
+ replaceRange(text, start_pos, end_pos);
+ }
+
+ public native void setText(String text);
+
+ public native void select(int start_pos, int end_pos);
+
+ public native void setEditable(boolean editable);
+
+ public native void setCaretPosition(int pos);
+
+ public InputMethodRequests getInputMethodRequests()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtTextFieldPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtTextFieldPeer.java
new file mode 100644
index 000000000..f92943202
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtTextFieldPeer.java
@@ -0,0 +1,159 @@
+/* QtTextFieldPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.TextField;
+import java.awt.event.TextEvent;
+import java.awt.im.InputMethodRequests;
+import java.awt.peer.TextFieldPeer;
+
+public class QtTextFieldPeer extends QtComponentPeer implements TextFieldPeer
+{
+ public QtTextFieldPeer( QtToolkit kit, TextField owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ setText(((TextField)owner).getText());
+ setEditable(((TextField)owner).isEditable());
+ }
+
+ /**
+ * Called back on a text edit.
+ */
+ private void textChanged()
+ {
+ TextEvent e = new TextEvent(owner, TextEvent.TEXT_VALUE_CHANGED);
+ QtToolkit.eventQueue.postEvent(e);
+ }
+
+ /**
+ * Returns the start (start = true) or end (start = false) of the selection.
+ */
+ private native int getSelection(boolean start);
+
+ private native Dimension getMinimumSizeNative(int columns);
+
+ private native Dimension getPreferredSizeNative(int columns);
+
+ // ************ Public methods *********************
+
+ public long filterEvents(long e)
+ {
+ return e;
+ }
+
+ public native int getCaretPosition();
+
+ public Rectangle getCharacterBounds(int i)
+ {
+ return new Rectangle(0,0,0,0);
+ }
+
+ public int getIndexAtPoint(int x, int y)
+ {
+ // FIXME
+ return 0;
+ }
+
+ public Dimension getMinimumSize(int columns)
+ {
+ Dimension d = getMinimumSizeNative( columns );
+ if ( d == null )
+ return new Dimension(10, 10);
+ return d;
+ }
+
+ public Dimension getPreferredSize(int columns)
+ {
+ Dimension d = getPreferredSizeNative( columns );
+ if ( d == null )
+ return owner.getSize();
+ return d;
+ }
+
+ public int getSelectionEnd()
+ {
+ return getSelection(false);
+ }
+
+ public int getSelectionStart()
+ {
+ return getSelection(true);
+ }
+
+ public native String getText();
+
+ public Dimension minimumSize(int cols)
+ {
+ return getMinimumSize(cols);
+ }
+
+ public Dimension preferredSize(int cols)
+ {
+ return getPreferredSize(cols);
+ }
+
+ public native void select(int selStart, int selEnd);
+
+ public native void setCaretPosition(int pos);
+
+ public void setEchoCharacter(char c)
+ {
+ setEchoChar(c);
+ }
+
+ public native void setEchoChar(char echoChar);
+
+ public native void setEditable(boolean editable);
+
+ public native void setText(String l);
+
+ public InputMethodRequests getInputMethodRequests()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java b/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java
new file mode 100644
index 000000000..9f8a691c6
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtToolkit.java
@@ -0,0 +1,470 @@
+/* QtToolkit.java --
+ Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.EmbeddedWindow;
+import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.peer.EmbeddedWindowPeer;
+
+import java.awt.AWTException;
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Checkbox;
+import java.awt.CheckboxMenuItem;
+import java.awt.Choice;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.FileDialog;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.PopupMenu;
+import java.awt.PrintJob;
+import java.awt.ScrollPane;
+import java.awt.Scrollbar;
+import java.awt.TextArea;
+import java.awt.TextField;
+import java.awt.Window;
+import java.awt.datatransfer.Clipboard;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.event.AWTEventListener;
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.awt.peer.CheckboxPeer;
+import java.awt.peer.ChoicePeer;
+import java.awt.peer.DialogPeer;
+import java.awt.peer.FileDialogPeer;
+import java.awt.peer.FontPeer;
+import java.awt.peer.FramePeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.ListPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.PopupMenuPeer;
+import java.awt.peer.RobotPeer;
+import java.awt.peer.ScrollPanePeer;
+import java.awt.peer.ScrollbarPeer;
+import java.awt.peer.TextAreaPeer;
+import java.awt.peer.TextFieldPeer;
+import java.awt.peer.WindowPeer;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+public class QtToolkit extends ClasspathToolkit
+{
+ public static EventQueue eventQueue = null; // the native event queue
+ public static QtRepaintThread repaintThread = null;
+ public static MainQtThread guiThread = null;
+ public static QtGraphicsEnvironment graphicsEnv = null;
+
+ private static void initToolkit()
+ {
+ eventQueue = new EventQueue();
+ repaintThread = new QtRepaintThread();
+ System.loadLibrary("qtpeer");
+
+ String theme = null;
+ try
+ {
+ String style = System.getProperty("qtoptions.style");
+ if(style != null)
+ theme = style;
+ }
+ catch(SecurityException e)
+ {
+ }
+ catch(IllegalArgumentException e)
+ {
+ }
+
+ boolean doublebuffer = true;
+ try
+ {
+ String style = System.getProperty("qtoptions.nodoublebuffer");
+ if(style != null)
+ doublebuffer = false;
+ }
+ catch(SecurityException e)
+ {
+ }
+ catch(IllegalArgumentException e)
+ {
+ }
+
+ guiThread = new MainQtThread( theme, doublebuffer );
+ guiThread.start();
+ repaintThread.start();
+ }
+
+ /**
+ * Construct the toolkit!
+ */
+ public QtToolkit()
+ {
+ if( guiThread == null )
+ initToolkit();
+
+ // make sure the GUI thread has started.
+ while (!guiThread.isRunning())
+ ;
+
+ if( graphicsEnv == null )
+ graphicsEnv = new QtGraphicsEnvironment( this );
+ }
+
+ native String[] nativeFontFamilies();
+
+ native int numScreens();
+
+ native int defaultScreen();
+
+ // ************ Public methods *********************
+
+ public synchronized native void beep();
+
+ public int checkImage(Image image, int w, int h, ImageObserver observer)
+ {
+ if(image instanceof QtImage)
+ return ((QtImage)image).checkImage(observer);
+
+ return ImageObserver.ERROR; // FIXME
+ }
+
+ protected ButtonPeer createButton( Button target )
+ {
+ return new QtButtonPeer( this, target );
+ }
+
+ protected CanvasPeer createCanvas(Canvas target)
+ {
+ return new QtCanvasPeer( this, target );
+ }
+
+ protected CheckboxPeer createCheckbox(Checkbox target)
+ {
+ return new QtCheckboxPeer( this, target );
+ }
+
+ protected ChoicePeer createChoice(Choice target)
+ {
+ return new QtChoicePeer( this, target );
+ }
+
+ protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target)
+ {
+ return new QtMenuItemPeer( this, target );
+ }
+
+ public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge)
+ {
+ throw new RuntimeException("Not implemented");
+ }
+
+ protected FramePeer createFrame(Frame target)
+ {
+ return new QtFramePeer( this, target );
+ }
+
+ protected FileDialogPeer createFileDialog(FileDialog target)
+ {
+ return new QtFileDialogPeer( this, target );
+ }
+
+ public Image createImage(ImageProducer producer)
+ {
+ return new QtImage( producer );
+ }
+
+ public Image createImage(byte[] imageData,
+ int imageOffset,
+ int imageLength)
+ {
+ byte[] dataCopy = new byte[imageLength];
+ System.arraycopy(imageData, imageOffset, dataCopy, 0, imageLength);
+ return new QtImage( dataCopy );
+ }
+
+ public Image createImage(String filename)
+ {
+ return new QtImage( filename );
+ }
+
+ public Image createImage(URL url)
+ {
+ return new QtImage( url );
+ }
+
+ protected TextFieldPeer createTextField(TextField target)
+ {
+ return new QtTextFieldPeer(this,target);
+ }
+
+ protected LabelPeer createLabel(Label target)
+ {
+ return new QtLabelPeer( this, target );
+ }
+
+ protected ListPeer createList(List target)
+ {
+ return new QtListPeer( this, target );
+ }
+
+ protected ScrollbarPeer createScrollbar(Scrollbar target)
+ {
+ return new QtScrollbarPeer( this, target );
+ }
+
+ protected ScrollPanePeer createScrollPane(ScrollPane target)
+ {
+ return new QtScrollPanePeer( this, target );
+ }
+
+ protected TextAreaPeer createTextArea(TextArea target)
+ {
+ return new QtTextAreaPeer( this, target );
+ }
+
+ protected PanelPeer createPanel(Panel target)
+ {
+ return new QtPanelPeer( this, target);
+ }
+
+ protected WindowPeer createWindow(Window target)
+ {
+ return new QtWindowPeer( this, target );
+ }
+
+ protected DialogPeer createDialog(Dialog target)
+ {
+ return new QtDialogPeer( this, target );
+ }
+
+ protected MenuBarPeer createMenuBar(MenuBar target)
+ {
+ return new QtMenuBarPeer( this, target );
+ }
+
+ protected MenuPeer createMenu(Menu target)
+ {
+ return new QtMenuPeer( this, target );
+ }
+
+ protected PopupMenuPeer createPopupMenu(PopupMenu target)
+ {
+ return new QtPopupMenuPeer( this, target );
+ }
+
+ protected MenuItemPeer createMenuItem(MenuItem target)
+ {
+ return new QtMenuItemPeer( this, target );
+ }
+
+ /**
+ * @since 1.4
+ */
+ public AWTEventListener[] getAWTEventListeners()
+ {
+ return null; // FIXME
+ }
+
+ /**
+ * @since 1.4
+ */
+ public AWTEventListener[] getAWTEventListeners(long mask)
+ {
+ return null; // FIXME
+ }
+
+ public ColorModel getColorModel()
+ {
+ return new DirectColorModel(32,
+ 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF,
+ 0xFF000000);
+ }
+
+ /**
+ * Just return the defaults.
+ */
+ public String[] getFontList()
+ {
+ String[] builtIn = new String[] { "Dialog",
+ "DialogInput",
+ "Monospaced",
+ "Serif",
+ "SansSerif" };
+ String[] nat = nativeFontFamilies();
+ String[] allFonts = new String[ nat.length + 5 ];
+ System.arraycopy(builtIn, 0, allFonts, 0, 5);
+ System.arraycopy(nat, 0, allFonts, 5, nat.length);
+ return allFonts;
+ }
+
+ public FontMetrics getFontMetrics(Font font)
+ {
+ return new QtFontMetrics(font);
+ }
+
+ protected FontPeer getFontPeer(String name,
+ int style)
+ {
+ Map attrs = new HashMap ();
+ ClasspathFontPeer.copyStyleToAttrs(style, attrs);
+ ClasspathFontPeer.copySizeToAttrs(12, attrs); // Default size is 12.
+ return getClasspathFontPeer (name, attrs);
+ }
+
+ public Image getImage(String filename)
+ {
+ return new QtImage(filename);
+ }
+
+ public Image getImage(URL url)
+ {
+ return createImage( url );
+ }
+
+ public PrintJob getPrintJob(Frame frame,
+ String jobtitle,
+ Properties props)
+ {
+ SecurityManager sm;
+ sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPrintJobAccess();
+
+ throw new RuntimeException("Not implemented");
+ }
+
+ public Clipboard getSystemClipboard()
+ {
+ throw new RuntimeException("Not implemented");
+ }
+
+ protected EventQueue getSystemEventQueueImpl()
+ {
+ return eventQueue;
+ }
+
+ public native Dimension getScreenSize();
+
+ public native int getScreenResolution();
+
+ public Map mapInputMethodHighlight(InputMethodHighlight highlight)
+ {
+ return null; // FIXME
+ }
+
+ public boolean prepareImage(Image image, int w, int h, ImageObserver observer)
+ {
+ if(image instanceof QtImage)
+ return true;
+ return false; // FIXME?
+ }
+
+ public native void sync();
+
+ // ********************** ClasspathToolkit methods
+
+ public GraphicsEnvironment getLocalGraphicsEnvironment()
+ {
+ return graphicsEnv;
+ }
+
+ public ClasspathFontPeer getClasspathFontPeer (String name, Map attrs)
+ {
+ return new QtFontPeer (name, attrs);
+ }
+
+ // FIXME
+ public Font createFont(int format, InputStream stream)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ // FIXME
+ public RobotPeer createRobot (GraphicsDevice screen) throws AWTException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public EmbeddedWindowPeer createEmbeddedWindow(EmbeddedWindow w)
+ {
+ // return new QtEmbeddedWindowPeer( this, w );
+ return null;
+ }
+
+ @Override
+ public boolean isModalExclusionTypeSupported
+ (Dialog.ModalExclusionType modalExclusionType)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isModalityTypeSupported(Dialog.ModalityType modalityType)
+ {
+ return false;
+ }
+
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtVolatileImage.java b/libjava/classpath/gnu/java/awt/peer/qt/QtVolatileImage.java
new file mode 100644
index 000000000..a203de0d0
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtVolatileImage.java
@@ -0,0 +1,434 @@
+/* QtVolatileImage.java --
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Color;
+import java.awt.Image;
+import java.awt.ImageCapabilities;
+import java.awt.GraphicsConfiguration;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.MemoryImageSource;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.image.VolatileImage;
+import java.util.Hashtable;
+import java.util.WeakHashMap;
+
+/**
+ * QtVolatileImage - wraps a QImage
+ *
+ */
+public class QtVolatileImage extends VolatileImage
+{
+ int width = -1, height = -1;
+
+ /**
+ * Properties.
+ */
+ Hashtable props;
+
+ /**
+ * Pointer to the QImage
+ */
+ long nativeObject;
+
+ /*
+ * The 32-bit AARRGGBB format the uses.
+ */
+ static ColorModel nativeModel = new DirectColorModel(32,
+ 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF,
+ 0xFF000000);
+
+ /**
+ * Clears the image to RGBA 0
+ */
+ public native void clear();
+
+ /**
+ * Returns a copy of the pixel data as a java array.
+ */
+ private native int[] getPixels();
+
+ /**
+ * Allocates a QImage
+ */
+ private native void createImage();
+
+ /**
+ * HashMap of Graphics objects painting on this Image.
+ */
+ WeakHashMap painters;
+
+ /**
+ * Flags if this image is to be destroyed.
+ */
+ boolean killFlag;
+
+ /**
+ * Frees the above.
+ */
+ private native void freeImage();
+
+ /**
+ * Blit a QImage
+ */
+ public native void blit(QtImage i);
+ public native void blit(QtImage i, int x, int y, int w, int h);
+
+ /**
+ * Sets the image to scaled copy of src image. hints are rendering hints.
+ */
+ private native void createScaledImage(QtVolatileImage src, int hints);
+
+ /**
+ * Draws the image optionally composited.
+ */
+ private native void drawPixels (QtGraphics gc,
+ int bg_red, int bg_green, int bg_blue,
+ int x, int y,
+ boolean composite);
+ /**
+ * Draws the image, optionally scaled and composited.
+ */
+ private native void drawPixelsScaled (QtGraphics gc,
+ int bg_red, int bg_green, int bg_blue,
+ int x, int y, int width, int height,
+ boolean composite);
+
+ /**
+ * Draws the image transformed.
+ */
+ private native void drawPixelsTransformed (QtGraphics gc, QMatrix transform);
+
+ /**
+ * Draws the image scaled flipped and optionally composited.
+ */
+ native void drawPixelsScaledFlipped (QtGraphics gc,
+ int bg_red, int bg_green,
+ int bg_blue,
+ boolean flipX, boolean flipY,
+ int srcX, int srcY,
+ int srcWidth, int srcHeight,
+ int dstX, int dstY,
+ int dstWidth, int dstHeight,
+ boolean composite);
+
+ /**
+ * Constructs an empty QtVolatileImage.
+ */
+ public QtVolatileImage (int width, int height)
+ {
+ this.width = width;
+ this.height = height;
+ props = new Hashtable();
+ createImage();
+ clear();
+ }
+
+ /**
+ * Constructs a scaled version of the src bitmap, using Qt
+ */
+ private QtVolatileImage (QtVolatileImage src, int width, int height,
+ int hints)
+ {
+ this.width = width;
+ this.height = height;
+ props = new Hashtable();
+
+ createScaledImage(src, hints);
+ }
+
+
+ public void finalize()
+ {
+ dispose();
+ }
+
+ public void dispose()
+ {
+ if( painters == null || painters.isEmpty() )
+ freeImage();
+ else
+ killFlag = true; // can't destroy image yet.
+ // Do so when all painters are gone.
+ }
+
+ // java.awt.Image methods ////////////////////////////////////////////////
+
+ public int getWidth (ImageObserver observer)
+ {
+ return getWidth();
+ }
+
+ public int getHeight (ImageObserver observer)
+ {
+ return getHeight();
+ }
+
+ public Object getProperty (String name, ImageObserver observer)
+ {
+ Object value = props.get (name);
+ return (value == null) ? UndefinedProperty : value;
+ }
+
+ /**
+ * Returns the source of this image.
+ */
+ public ImageProducer getSource ()
+ {
+ return new MemoryImageSource(width, height, nativeModel, getPixels(),
+ 0, width);
+ }
+
+ void putPainter(QtImageGraphics g)
+ {
+ if( painters == null )
+ painters = new WeakHashMap();
+ painters.put( g, "dummy" );
+ }
+
+ void removePainter(QtImageGraphics g)
+ {
+ painters.remove( g );
+ if( killFlag && painters.isEmpty() )
+ freeImage();
+ }
+
+ /**
+ * Creates a Graphics context for this image.
+ */
+ public Graphics getGraphics ()
+ {
+ QtImageGraphics g = new QtImageGraphics( this );
+ putPainter( g );
+ return g;
+ }
+
+ /**
+ * Returns a scaled instance of this image.
+ */
+ public Image getScaledInstance(int width,
+ int height,
+ int hints)
+ {
+ if (width <= 0 || height <= 0)
+ throw new IllegalArgumentException("Width and height of scaled bitmap"+
+ "must be >= 0");
+
+ return new QtVolatileImage(this, width, height, hints);
+ }
+
+ /**
+ */
+ public void flush ()
+ {
+ // FIXME ?
+ }
+
+ /**
+ * Returns the image status, used by QtToolkit
+ */
+ public int checkImage (ImageObserver observer)
+ {
+ return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT;
+ }
+
+ // Drawing methods ////////////////////////////////////////////////
+
+ /**
+ * Draws an image with eventual scaling/transforming.
+ */
+ public boolean drawImage (QtGraphics g, QMatrix matrix,
+ ImageObserver observer)
+ {
+ drawPixelsTransformed (g, matrix);
+ return true;
+ }
+
+ /**
+ * Draws an image to the QtGraphics context, at (x,y) with optional
+ * compositing with a background color.
+ */
+ public boolean drawImage (QtGraphics g, int x, int y,
+ Color bgcolor, ImageObserver observer)
+ {
+ if(bgcolor != null)
+ drawPixels(g, bgcolor.getRed (), bgcolor.getGreen (),
+ bgcolor.getBlue (), x, y, true);
+ else
+ drawPixels(g, 0, 0, 0, x, y, false);
+
+ return true;
+ }
+
+ /**
+ * Draws an image to the QtGraphics context, at (x,y) scaled to
+ * width and height, with optional compositing with a background color.
+ */
+ public boolean drawImage (QtGraphics g, int x, int y, int width, int height,
+ Color bgcolor, ImageObserver observer)
+ {
+ if(bgcolor != null)
+ drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (),
+ bgcolor.getBlue (), x, y, width, height, true);
+ else
+ drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false);
+
+ return true;
+ }
+
+ /**
+ * Draws an image with eventual scaling/transforming.
+ */
+ public boolean drawImage (QtGraphics g, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2,
+ Color bgcolor, ImageObserver observer)
+ {
+ boolean flipX = (dx1 > dx2)^(sx1 > sx2);
+ boolean flipY = (dy1 > dy2)^(sy1 > sy2);
+ int dstWidth = Math.abs (dx2 - dx1);
+ int dstHeight = Math.abs (dy2 - dy1);
+ int srcWidth = Math.abs (sx2 - sx1);
+ int srcHeight = Math.abs (sy2 - sy1);
+ int srcX = (sx1 < sx2) ? sx1 : sx2;
+ int srcY = (sy1 < sy2) ? sy1 : sy2;
+ int dstX = (dx1 < dx2) ? dx1 : dx2;
+ int dstY = (dy1 < dy2) ? dy1 : dy2;
+
+ // Clipping. This requires the dst to be scaled as well,
+ if (srcWidth > width)
+ {
+ dstWidth = (int)((double)dstWidth*((double)width/(double)srcWidth));
+ srcWidth = width - srcX;
+ }
+
+ if (srcHeight > height)
+ {
+ dstHeight = (int)((double)dstHeight*((double)height/(double)srcHeight));
+ srcHeight = height - srcY;
+ }
+
+ if (srcWidth + srcX > width)
+ {
+ dstWidth = (int)((double)dstWidth * (double)(width - srcX)/(double)srcWidth);
+ srcWidth = width - srcX;
+ }
+
+ if (srcHeight + srcY > height)
+ {
+ dstHeight = (int)((double)dstHeight * (double)(width - srcY)/(double)srcHeight);
+ srcHeight = height - srcY;
+ }
+
+ if ( srcWidth <= 0 || srcHeight <= 0 || dstWidth <= 0 || dstHeight <= 0)
+ return true;
+
+ if(bgcolor != null)
+ drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (),
+ bgcolor.getBlue (),
+ flipX, flipY,
+ srcX, srcY,
+ srcWidth, srcHeight,
+ dstX, dstY,
+ dstWidth, dstHeight,
+ true);
+ else
+ drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY,
+ srcX, srcY, srcWidth, srcHeight,
+ dstX, dstY, dstWidth, dstHeight,
+ false);
+ return true;
+ }
+
+ public native void copyArea(int x, int y, int width, int height,
+ int dx, int dy);
+
+ //******************** VolatileImage stuff ********************
+
+ public boolean contentsLost()
+ {
+ return false;
+ }
+
+ public Graphics2D createGraphics()
+ {
+ QtImageGraphics g = new QtImageGraphics(this);
+ putPainter( g );
+ return g;
+ }
+
+ public ImageCapabilities getCapabilities()
+ {
+ return new ImageCapabilities(false)
+ {
+ public boolean isTrueVolatile()
+ {
+ return false;
+ }
+ };
+ }
+
+ public int getHeight()
+ {
+ return height;
+ }
+
+ public BufferedImage getSnapshot()
+ {
+ BufferedImage bi = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB_PRE);
+ bi.setRGB( 0, 0, width, height, getPixels(), 0, width);
+ return bi;
+ }
+
+ public int getWidth()
+ {
+ return width;
+ }
+
+ public int validate(GraphicsConfiguration gc)
+ {
+ return IMAGE_OK;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/qt/QtWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/qt/QtWindowPeer.java
new file mode 100644
index 000000000..2dfe2ec5a
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/qt/QtWindowPeer.java
@@ -0,0 +1,105 @@
+/* QtWindowPeer.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.qt;
+
+import java.awt.Component;
+import java.awt.peer.WindowPeer;
+
+public class QtWindowPeer extends QtContainerPeer implements WindowPeer
+{
+ public QtWindowPeer( QtToolkit kit, Component owner )
+ {
+ super( kit, owner );
+ }
+
+ protected native void init();
+
+ protected void setup()
+ {
+ super.setup();
+ }
+
+ // ************ Public methods *********************
+
+ public native void toBack();
+
+ public native void toFront();
+
+ /*
+ * Belongs to Frame and Dialog, but no sense in duplicating code.
+ */
+ public native void setTitle(String title);
+
+ public void updateAlwaysOnTop()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean requestWindowFocus()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void updateIconImages()
+ {
+ // TODO: Implement properly.
+ }
+
+ public void updateMinimumSize()
+ {
+ // TODO: Implement properly.
+ }
+
+ public void setModalBlocked(java.awt.Dialog d, boolean b)
+ {
+ // TODO: Implement properly.
+ }
+
+ public void updateFocusableWindowState()
+ {
+ // TODO: Implement properly.
+ }
+
+ public void setAlwaysOnTop(boolean b)
+ {
+ // TODO: Implement properly.
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java
new file mode 100644
index 000000000..1a42fc953
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingButtonPeer.java
@@ -0,0 +1,261 @@
+/* SwingButtonPeer.java -- A Swing based peer for AWT buttons
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Button;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.ButtonPeer;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+
+/**
+ * A Swing based peer for the AWT button.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingButtonPeer
+ extends SwingComponentPeer
+ implements ButtonPeer
+{
+
+ /**
+ * A specialized Swing button to be used as AWT button.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ class SwingButton
+ extends JButton
+ implements SwingComponent
+ {
+ Button button;
+
+ SwingButton(Button button)
+ {
+ this.button = button;
+ }
+
+ /**
+ * Overridden so that this method returns the correct value even without a
+ * peer.
+ *
+ * @return the screen location of the button
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingButtonPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value for the
+ * swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (button != null)
+ retVal = button.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingButtonPeer.this.createImage(w, h);
+ }
+
+ /**
+ * Overridden, so that the Swing button can create a Graphics without its
+ * own peer.
+ *
+ * @return a graphics instance for the button
+ */
+ public Graphics getGraphics()
+ {
+ return SwingButtonPeer.this.getGraphics();
+ }
+
+ /**
+ * Returns this button.
+ *
+ * @return this button
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code> after having retargetted it to this
+ * button.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to
+ * <code>processMouseMotionEvent()</code> after having retargetted it to
+ * this button.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to
+ * <code>processKeyEvent()</code> after having retargetted it to this
+ * button.
+ *
+ * @param ev the mouse event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ ev.setSource(this);
+ processKeyEvent(ev);
+ }
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (button != null)
+ par = button.getParent();
+ return par;
+ }
+
+ /**
+ * Handles focus events by forwarding it to
+ * <code>processFocusEvent()</code>.
+ *
+ * @param ev the Focus event
+ */
+ public void handleFocusEvent(FocusEvent ev)
+ {
+ processFocusEvent(ev);
+ }
+
+ public void requestFocus() {
+ SwingButtonPeer.this.requestFocus(awtComponent, false, true, 0);
+ }
+
+ public boolean requestFocus(boolean temporary) {
+ return SwingButtonPeer.this.requestFocus(awtComponent, temporary,
+ true, 0);
+ }
+ }
+
+ /**
+ * Listens for ActionEvents on the Swing button and triggers corresponding
+ * ActionEvents on the AWT button.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ class SwingButtonListener implements ActionListener
+ {
+
+ /**
+ * Receives notification when an action was performend on the button.
+ *
+ * @param event the action event
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ Button b = (Button) SwingButtonPeer.this.awtComponent;
+ ActionListener[] l = b.getActionListeners();
+ if (l.length == 0)
+ return;
+ ActionEvent ev = new ActionEvent(b, ActionEvent.ACTION_PERFORMED,
+ b.getActionCommand());
+ for (int i = 0; i < l.length; ++i)
+ l[i].actionPerformed(ev);
+ }
+
+ }
+
+ /**
+ * Constructs a new SwingButtonPeer.
+ *
+ * @param theButton the AWT button for this peer
+ */
+ public SwingButtonPeer(Button theButton)
+ {
+ SwingButton button = new SwingButton(theButton);
+ button.setText(theButton.getLabel());
+ button.addActionListener(new SwingButtonListener());
+ init(theButton, button);
+ }
+
+ /**
+ * Sets the label of the button. This call is forwarded to the setText method
+ * of the managed Swing button.
+ *
+ * @param label the label to set
+ */
+ public void setLabel(String label)
+ {
+ ((SwingButton) swingComponent).setText(label);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingCanvasPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingCanvasPeer.java
new file mode 100644
index 000000000..abef9ef12
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingCanvasPeer.java
@@ -0,0 +1,64 @@
+/* SwingCanvasPeer.java -- A canvas peer based on Swing
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Canvas;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.LightweightPeer;
+
+/**
+ * A CanvasPeer to be used together with the Swing peers.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingCanvasPeer
+ extends SwingComponentPeer
+ implements LightweightPeer, CanvasPeer
+{
+
+ /**
+ * Creates a new <code>SwingCanvasPeer</code> for the specified Canvas.
+ *
+ * @param canvas the canvas.
+ */
+ public SwingCanvasPeer(Canvas canvas)
+ {
+ init(canvas, null);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingCheckboxPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingCheckboxPeer.java
new file mode 100755
index 000000000..7080831a2
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingCheckboxPeer.java
@@ -0,0 +1,256 @@
+/* SwingCheckboxPeer.java -- A Swing based peer for AWT checkboxes
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Checkbox;
+import java.awt.CheckboxGroup;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.event.FocusEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.CheckboxPeer;
+
+import javax.swing.JCheckBox;
+import javax.swing.JComponent;
+import javax.swing.JToggleButton;
+
+/**
+ * A CheckboxPeer implementation that is backed by the Swing JCheckBox.
+ */
+public class SwingCheckboxPeer extends SwingComponentPeer implements
+ CheckboxPeer {
+
+ /**
+ * A spezialized Swing checkbox used to paint the checkbox for the
+ * AWT checkbox.
+ */
+ private class SwingCheckbox
+ extends JCheckBox
+ implements SwingComponent
+ {
+ Checkbox checkbox;
+
+ SwingCheckbox(Checkbox checkbox)
+ {
+ this.checkbox = checkbox;
+ }
+
+ /**
+ * Returns this checkbox.
+ *
+ * @return <code>this</code>
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to
+ * <code>processMouseMotionEvent()</code>.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to <code>processKeyEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ ev.setSource(this);
+ processKeyEvent(ev);
+ }
+
+ /**
+ * Handles focus events by forwarding it to
+ * <code>processFocusEvent()</code>.
+ *
+ * @param ev the Focus event
+ */
+ public void handleFocusEvent(FocusEvent ev)
+ {
+ processFocusEvent(ev);
+ }
+
+ /**
+ * Overridden so that this method returns the correct value even without a
+ * peer.
+ *
+ * @return the screen location of the button
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingCheckboxPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value
+ * for the swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (checkbox != null)
+ retVal = checkbox.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingCheckboxPeer.this.createImage(w, h);
+ }
+
+ public Graphics getGraphics()
+ {
+ return SwingCheckboxPeer.this.getGraphics();
+ }
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (checkbox != null)
+ par = checkbox.getParent();
+ return par;
+ }
+
+ public void requestFocus() {
+ SwingCheckboxPeer.this.requestFocus(awtComponent, false, true, 0);
+ }
+
+ public boolean requestFocus(boolean temporary) {
+ return SwingCheckboxPeer.this.requestFocus(awtComponent, temporary,
+ true, 0);
+ }
+ }
+
+ /**
+ * Listens for ActionEvents on the Swing button and triggers corresponding
+ * ActionEvents on the AWT button.
+ */
+ class SwingCheckboxListener implements ItemListener
+ {
+ Checkbox awtCheckbox;
+
+ SwingCheckboxListener(Checkbox checkbox)
+ {
+ awtCheckbox = checkbox;
+ }
+
+ /**
+ * Receives notification when an action was performend on the button.
+ *
+ * @param event the action event
+ */
+ public void itemStateChanged(ItemEvent event)
+ {
+ awtCheckbox.setState(event.getStateChange()==ItemEvent.SELECTED);
+ ItemListener[] l = awtCheckbox.getItemListeners();
+ if (l.length == 0)
+ return;
+ ItemEvent ev = new ItemEvent(awtCheckbox, ItemEvent.ITEM_STATE_CHANGED,
+ awtCheckbox, event.getStateChange());
+ for (int i = 0; i < l.length; ++i)
+ l[i].itemStateChanged(ev);
+ }
+ }
+
+ /**
+ * Creates a new SwingCheckboxPeer instance.
+ */
+ public SwingCheckboxPeer(Checkbox checkbox)
+ {
+ SwingCheckbox swingCheckbox = new SwingCheckbox(checkbox);
+ swingCheckbox.addItemListener(new SwingCheckboxListener(checkbox));
+
+ init(checkbox, swingCheckbox);
+ setLabel(checkbox.getLabel());
+ setState(checkbox.getState());
+ }
+
+ public void setCheckboxGroup(CheckboxGroup group)
+ {
+ // TODO: Implement this.
+ }
+
+ public void setLabel(String label)
+ {
+ ((JToggleButton) swingComponent).setText(label);
+ }
+
+ public void setState(boolean state)
+ {
+ ((JToggleButton) swingComponent).setSelected(state);
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java
new file mode 100644
index 000000000..ca42fb748
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponent.java
@@ -0,0 +1,99 @@
+/* SwingComponent.java -- An interface that defines a Swing component for peers
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+
+import javax.swing.JComponent;
+
+/**
+ * Defines some additional methods that the Swing components must implement
+ * in order to work with the Swing peers. This is usually achieved by
+ * subclassing a Swing component and forwarding the method calls to some
+ * protected JComponent method.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public interface SwingComponent
+{
+
+ /**
+ * Returns the actual swing compenent.
+ *
+ * @return the actual swing compenent
+ */
+ JComponent getJComponent();
+
+ /**
+ * Handles a mouse event. This is usually forwarded to
+ * {@link Component#processMouseMotionEvent(MouseEvent)} of the swing
+ * component.
+ *
+ * @param ev the mouse event
+ */
+ void handleMouseEvent(MouseEvent ev);
+
+ /**
+ * Handles a mouse motion event. This is usually forwarded to
+ * {@link Component#processMouseEvent(MouseEvent)} of the swing
+ * component.
+ *
+ * @param ev the mouse motion event
+ */
+ void handleMouseMotionEvent(MouseEvent ev);
+
+ /**
+ * Handles a key event. This is usually forwarded to
+ * {@link Component#processKeyEvent(KeyEvent)} of the swing
+ * component.
+ *
+ * @param ev the key event
+ */
+ void handleKeyEvent(KeyEvent ev);
+
+ /**
+ * Handles a focus event. This is usually forwarded to
+ * {@link Component#processFocusEvent(FocusEvent)} of the swing
+ * component.
+ *
+ * @param ev the focus event
+ */
+ void handleFocusEvent(FocusEvent ev);
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java
new file mode 100644
index 000000000..8be95dcb7
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingComponentPeer.java
@@ -0,0 +1,1136 @@
+/* SwingComponentPeer.java -- An abstract base class for Swing based peers
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.AWTEvent;
+import java.awt.AWTException;
+import java.awt.BufferCapabilities;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.BufferCapabilities.FlipContents;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.PaintEvent;
+import java.awt.image.ColorModel;
+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.awt.peer.LightweightPeer;
+
+import javax.swing.JComponent;
+import javax.swing.RepaintManager;
+
+/**
+ * The base class for Swing based component peers. This provides the basic
+ * functionality needed for Swing based component peers. Many methods are
+ * implemented to forward to the Swing component. Others however forward
+ * to the component's parent and expect the toplevel component peer to provide
+ * a real implementation of it. These are for example the key methods
+ * {@link #getGraphics()} and {@link #createImage(int, int)}, as well as
+ * {@link #getLocationOnScreen()}.
+ *
+ * This class also provides the necesary hooks into the Swing painting and
+ * event handling system. In order to achieve this, it traps paint, mouse and
+ * key events in {@link #handleEvent(AWTEvent)} and calls some special methods
+ * ({@link #peerPaint(Graphics)}, {@link #handleKeyEvent(KeyEvent)},
+ * {@link #handleMouseEvent(MouseEvent)} and
+ * {@link #handleMouseMotionEvent(MouseEvent)}) that call the corresponding
+ * Swing methods.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingComponentPeer
+ implements ComponentPeer
+{
+
+ /**
+ * The AWT component for this peer.
+ */
+ protected Component awtComponent;
+
+ /**
+ * The Swing component for this peer.
+ */
+ protected SwingComponent swingComponent;
+
+ /**
+ * The font that is set for this peer.
+ */
+ protected Font peerFont;
+
+ /**
+ * The current repaint area.
+ */
+ protected Rectangle paintArea;
+
+ /**
+ * Creates a SwingComponentPeer instance. Subclasses are expected to call
+ * this constructor and thereafter call {@link #init(Component, JComponent)}
+ * in order to setup the AWT and Swing components properly.
+ */
+ protected SwingComponentPeer()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Initializes the AWT and Swing component for this peer. It is expected that
+ * subclasses call this from within their constructor.
+ *
+ * @param awtComp the AWT component for this peer
+ * @param swingComp the Swing component for this peer
+ */
+ protected void init(Component awtComp, SwingComponent swingComp)
+ {
+ awtComponent = awtComp;
+ swingComponent = swingComp;
+ if (swingComponent != null)
+ {
+ JComponent c = swingComponent.getJComponent();
+ if (c != null)
+ {
+ c.addNotify();
+ RepaintManager.currentManager(c).setDoubleBufferingEnabled(false);
+ System.setProperty("gnu.awt.swing.doublebuffering", "true");
+ }
+ }
+
+ // Register this heavyweight component with the nearest heavyweight
+ // container, so we get peerPaint() triggered by that container.
+ if (! (this instanceof LightweightPeer))
+ {
+ Component comp = awtComponent;
+ Container parent = comp.getParent();
+ while (parent != null &&
+ ! (parent.getPeer() instanceof SwingContainerPeer))
+ {
+ comp = parent;
+ parent = comp.getParent();
+ }
+
+ // At this point we have the ancestor with a SwingContainerPeer
+ // (or null peer).
+ if (parent != null && parent.getPeer() instanceof SwingContainerPeer)
+ {
+ SwingContainerPeer p = (SwingContainerPeer) parent.getPeer();
+ p.addHeavyweightDescendent(awtComponent);
+ }
+ }
+ }
+
+ /**
+ * Returns the construction status of the specified image. This is called
+ * by {@link Component#checkImage(Image, int, int, ImageObserver)}.
+ *
+ * @param img the image
+ * @param width the width of the image
+ * @param height the height of the image
+ * @param ob the image observer to be notified of updates of the status
+ *
+ * @return a bitwise ORed set of ImageObserver flags
+ */
+ public int checkImage(Image img, int width, int height, ImageObserver ob)
+ {
+ return Toolkit.getDefaultToolkit().checkImage(img, width, height, ob);
+ }
+
+ /**
+ * Creates an image by starting the specified image producer. This is called
+ * by {@link Component#createImage(ImageProducer)}.
+ *
+ * @param prod the image producer to be used to create the image
+ *
+ * @return the created image
+ */
+ public Image createImage(ImageProducer prod)
+ {
+ Image image = Toolkit.getDefaultToolkit().createImage(prod);
+ return image;
+ }
+
+ /**
+ * Creates an empty image with the specified <code>width</code> and
+ * <code>height</code>.
+ *
+ * This is implemented to let the parent component create the image. This
+ * eventually goes up to the top-level component peer, which is then expected
+ * to deliver the image.
+ *
+ * @param width the width of the image to be created
+ * @param height the height of the image to be created
+ *
+ * @return the created image
+ */
+ public Image createImage(int width, int height)
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.createImage(width, height);
+ }
+
+ /**
+ * Disables the component. This is called by {@link Component#disable()}.
+ */
+ public void disable()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setEnabled(false);
+ }
+
+ /**
+ * Disposes the component peer. This should release all resources held by the
+ * peer. This is called when the component is no longer in use.
+ */
+ public void dispose()
+ {
+ // Unregister this heavyweight component from the nearest heavyweight
+ // container.
+ if (! (this instanceof LightweightPeer))
+ {
+ Component comp = awtComponent;
+ Container parent = comp.getParent();
+ while (parent != null &&
+ ! (parent.getPeer() instanceof SwingContainerPeer))
+ {
+ comp = parent;
+ parent = comp.getParent();
+ }
+
+ // At this point we have the ancestor with a SwingContainerPeer
+ // (or null peer).
+ if (parent != null && parent.getPeer() instanceof SwingContainerPeer)
+ {
+ SwingContainerPeer p = (SwingContainerPeer) parent.getPeer();
+ p.removeHeavyweightDescendent(awtComponent);
+ }
+ }
+
+ awtComponent = null;
+ swingComponent = null;
+ }
+
+ /**
+ * Enables the component. This is called by {@link Component#enable()}.
+ */
+ public void enable()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setEnabled(true);
+ }
+
+ /**
+ * Returns the color model of the component. This is currently not used.
+ *
+ * @return the color model of the component
+ */
+ public ColorModel getColorModel()
+ {
+ // FIXME: When this peer method will be used, we need to provide an
+ // implementation of this, probably forwarding to the toplevel peer, like
+ // in the other methods.
+ return null;
+ }
+
+ /**
+ * Returns the font metrics for the specified font. This is called by
+ * {@link Component#getFontMetrics(Font)}.
+ *
+ * This is implemented to query the font metrics from the parent component.
+ * This will eventually call the top-level component peer, which is then
+ * expected to deliver a font metrics object.
+ *
+ * @param f the font for which to query the font metrics
+ *
+ * @return the font metrics for the specified font
+ */
+ public FontMetrics getFontMetrics(Font f)
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.getFontMetrics(f);
+ }
+
+ /**
+ * Returns a {@link Graphics} object suitable for drawing on this component.
+ * This is called by {@link Component#getGraphics()}.
+ *
+ * This is implemented to query the graphics from the parent component and
+ * adjust the clip and translation to match this component.
+ * This will eventually call the top-level component peer, which is then
+ * expected to deliver a graphics object.
+ *
+ * @return a graphics object suitable for drawing on this component
+ */
+ public Graphics getGraphics()
+ {
+ Component parent = awtComponent.getParent();
+ Graphics g = parent.getGraphics();
+ g.translate(awtComponent.getX(), awtComponent.getY());
+ g.setClip(0, 0, awtComponent.getWidth(), awtComponent.getHeight());
+ return g;
+ }
+
+ /**
+ * Returns the location of this component in screen coordinates. This is
+ * called by {@link Component#getLocationOnScreen()}.
+ *
+ * This is implemented to query the parent component peer for its screen
+ * location and adds the offset of this component to it. This will eventually
+ * call the top-level component's peer, which is then expected to provide
+ * it's screen location.
+ *
+ * @return the location of this component in screen coordinates
+ */
+ public Point getLocationOnScreen()
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ Point location = parentPeer.getLocationOnScreen();
+ location.x += awtComponent.getX();
+ location.y += awtComponent.getY();
+ return location;
+ }
+
+ /**
+ * Returns the minimum size for the component. This is called by
+ * {@link Component#getMinimumSize()}.
+ *
+ * This is implemented to return the Swing component's minimum size.
+ *
+ * @return the minimum size for the component
+ */
+ public Dimension getMinimumSize()
+ {
+ return minimumSize();
+ }
+
+ /**
+ * Returns the preferred size for the component. This is called by
+ * {@link Component#getPreferredSize()}.
+ *
+ * This is implemented to return the Swing component's preferred size.
+ *
+ * @return the preferred size for the component
+ */
+ public Dimension getPreferredSize()
+ {
+ return preferredSize();
+ }
+
+ /**
+ * Returns the toolkit that created this peer.
+ *
+ * @return the toolkit that created this peer
+ */
+ public Toolkit getToolkit()
+ {
+ return Toolkit.getDefaultToolkit();
+ }
+
+ /**
+ * Handles the given event. This is called from
+ * {@link Component#dispatchEvent(AWTEvent)} to give the peer a chance to
+ * react to events for the component.
+ *
+ * @param e the event
+ */
+ public void handleEvent(AWTEvent e)
+ {
+ switch (e.getID())
+ {
+ case PaintEvent.UPDATE:
+ case PaintEvent.PAINT:
+ if (awtComponent.isShowing())
+ {
+ Rectangle clip ;
+ synchronized (this)
+ {
+ coalescePaintEvent((PaintEvent) e);
+ assert paintArea != null;
+ clip = paintArea;
+ paintArea = null;
+ }
+ Graphics g = awtComponent.getGraphics();
+ try
+ {
+ g.clipRect(clip.x, clip.y, clip.width, clip.height);
+ peerPaint(g, e.getID() == PaintEvent.UPDATE);
+ }
+ finally
+ {
+ g.dispose();
+ }
+ }
+ break;
+ case MouseEvent.MOUSE_PRESSED:
+ case MouseEvent.MOUSE_RELEASED:
+ case MouseEvent.MOUSE_CLICKED:
+ case MouseEvent.MOUSE_ENTERED:
+ case MouseEvent.MOUSE_EXITED:
+ handleMouseEvent((MouseEvent) e);
+ break;
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ handleMouseMotionEvent((MouseEvent) e);
+ break;
+ case KeyEvent.KEY_PRESSED:
+ case KeyEvent.KEY_RELEASED:
+ case KeyEvent.KEY_TYPED:
+ handleKeyEvent((KeyEvent) e);
+ break;
+ case FocusEvent.FOCUS_GAINED:
+ case FocusEvent.FOCUS_LOST:
+ handleFocusEvent((FocusEvent)e);
+ break;
+ default:
+ // Other event types are not handled here.
+ break;
+ }
+ }
+
+ /**
+ * Makes the component invisible. This is called from
+ * {@link Component#hide()}.
+ *
+ * This is implemented to call setVisible(false) on the Swing component.
+ */
+ public void hide()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setVisible(false);
+
+ Component parent = awtComponent.getParent();
+ if (parent != null)
+ parent.repaint(awtComponent.getX(), awtComponent.getY(),
+ awtComponent.getWidth(), awtComponent.getHeight());
+ }
+
+ /**
+ * Returns <code>true</code> if the component can receive keyboard input
+ * focus. This is called from {@link Component#isFocusTraversable()}.
+ *
+ * This is implemented to return isFocusable() from the Swing component.
+ *
+ * @specnote Part of the earlier 1.1 API, replaced by isFocusable().
+ */
+ public boolean isFocusTraversable()
+ {
+ return swingComponent != null ?
+ swingComponent.getJComponent().isFocusable() : false;
+ }
+
+ /**
+ * Returns <code>true</code> if the component can receive keyboard input
+ * focus. This is called from {@link Component#isFocusable()}.
+ *
+ * This is implemented to return isFocusable() from the Swing component.
+ */
+ public boolean isFocusable()
+ {
+ return swingComponent != null ?
+ swingComponent.getJComponent().isFocusable() : false;
+ }
+
+ /**
+ * Returns the minimum size for the component. This is called by
+ * {@link Component#minimumSize()}.
+ *
+ * This is implemented to return the Swing component's minimum size.
+ *
+ * @return the minimum size for the component
+ */
+ public Dimension minimumSize()
+ {
+ Dimension retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getMinimumSize();
+ else
+ retVal = new Dimension(0, 0);
+ return retVal;
+ }
+
+ /**
+ * Returns the preferred size for the component. This is called by
+ * {@link Component#getPreferredSize()}.
+ *
+ * This is implemented to return the Swing component's preferred size.
+ *
+ * @return the preferred size for the component
+ */
+ public Dimension preferredSize()
+ {
+ Dimension retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getPreferredSize();
+ else
+ retVal = new Dimension(0, 0);
+ return retVal;
+ }
+
+ /**
+ * Paints the component. This is triggered by
+ * {@link Component#paintAll(Graphics)}.
+ *
+ * @param graphics the graphics to paint with
+ */
+ public void paint(Graphics graphics)
+ {
+ peerPaint(graphics, false);
+ }
+
+ /**
+ * Prepares an image for rendering on this component. This is called by
+ * {@link Component#prepareImage(Image, int, int, ImageObserver)}.
+ *
+ * @param img the image to prepare
+ * @param width the desired width of the rendered image
+ * @param height the desired height of the rendered image
+ * @param ob the image observer to be notified of updates in the preparation
+ * process
+ *
+ * @return <code>true</code> if the image has been fully prepared,
+ * <code>false</code> otherwise (in which case the image observer
+ * receives updates)
+ */
+ public boolean prepareImage(Image img, int width, int height, ImageObserver ob)
+ {
+ Component parent = awtComponent.getParent();
+ if(parent != null)
+ {
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.prepareImage(img, width, height, ob);
+ }
+ else
+ {
+ return Toolkit.getDefaultToolkit().prepareImage(img, width, height, ob);
+ }
+ }
+
+ public void print(Graphics graphics)
+ {
+ // FIXME: I don't know what this method is supposed to do.
+ }
+
+ /**
+ * Repaints the specified rectangle of this component. This is called from
+ * {@link Component#repaint(long, int, int, int, int)}.
+ *
+ * This is implemented to call repaint() on the Swing component.
+ *
+ * @param tm number of milliseconds to wait with repainting
+ * @param x the X coordinate of the upper left corner of the damaged
+ * rectangle
+ * @param y the Y coordinate of the upper left corner of the damaged
+ * rectangle
+ * @param width the width of the damaged rectangle
+ * @param height the height of the damaged rectangle
+ */
+ public void repaint(long tm, int x, int y, int width, int height)
+ {
+ // NOTE: This is never called by AWT but is mandated by the peer interface.
+ if (swingComponent != null)
+ swingComponent.getJComponent().repaint(tm, x, y, width, height);
+ else
+ {
+ PaintEvent ev = new PaintEvent(awtComponent, PaintEvent.UPDATE,
+ new Rectangle(x, y, width, height));
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ev);
+ }
+ }
+
+ /**
+ * Requests that this component receives the focus. This is called from
+ * {@link Component#requestFocus()}.
+ *
+ * This calls requestFocus() on the Swing component.
+ *
+ * @specnote Part of the earlier 1.1 API, apparently replaced by argument
+ * form of the same method.
+ */
+ public void requestFocus()
+ {
+ // NOTE: This is never called by AWT but is mandated by the peer interface.
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ EventQueue q = tk.getSystemEventQueue();
+ q.postEvent(new FocusEvent(awtComponent, FocusEvent.FOCUS_GAINED, false));
+ }
+
+ /**
+ * Requests that this component receives the focus. This is called from
+ * {@link Component#requestFocus()}.
+ *
+ * This calls requestFocus() on the Swing component.
+ *
+ * @param source the actual component that requests focus (may be a
+ * lightweight descendant of the heavyweight container)
+ * @param tmp true when the change is temporary
+ * @param allowWindowFocus
+ * @param tm the timestamp of the focus change
+ *
+ * @return true when the focus change is guaranteed to be granted, false
+ * otherwise
+ */
+ public boolean requestFocus(Component source, boolean tmp,
+ boolean allowWindowFocus, long tm)
+ {
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ EventQueue q = tk.getSystemEventQueue();
+ q.postEvent(new FocusEvent(source, FocusEvent.FOCUS_GAINED, tmp));
+ return true;
+ }
+
+ /**
+ * Notifies the peer that the bounds of this component have changed. This
+ * is called by {@link Component#reshape(int, int, int, int)}.
+ *
+ * This is implemented to call setBounds() on the Swing component.
+ *
+ * @param x the X coordinate of the upper left corner of the component
+ * @param y the Y coordinate of the upper left corner of the component
+ * @param width the width of the component
+ * @param height the height of the component
+ */
+ public void reshape(int x, int y, int width, int height)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setBounds(x, y, width, height);
+ }
+
+ /**
+ * Sets the background color of the component. This is called by
+ * {@link Component#setBackground(Color)}.
+ *
+ * This is implemented to call setBackground() on the Swing component.
+ *
+ * @param color the background color to set
+ */
+ public void setBackground(Color color)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setBackground(color);
+ }
+
+ /**
+ * Notifies the peer that the bounds of this component have changed. This
+ * is called by {@link Component#setBounds(int, int, int, int)}.
+ *
+ * This is implemented to call setBounds() on the Swing component.
+ *
+ * @param x the X coordinate of the upper left corner of the component
+ * @param y the Y coordinate of the upper left corner of the component
+ * @param width the width of the component
+ * @param height the height of the component
+ */
+ public void setBounds(int x, int y, int width, int height)
+ {
+ reshape(x, y, width, height);
+ }
+
+ /**
+ * Sets the cursor of the component. This is called by
+ * {@link Component#setCursor(Cursor)}.
+ *
+ * This is implemented to call setCursor() on the Swing component.
+ *
+ * @specnote Part of the earlier 1.1 API, apparently no longer needed.
+ */
+ public void setCursor(Cursor cursor)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setCursor(cursor);
+ }
+
+ /**
+ * Sets the enabled/disabled state of this component. This is called by
+ * {@link Component#setEnabled(boolean)}.
+ *
+ * This is implemented to call setEnabled() on the Swing component.
+ *
+ * @param enabled <code>true</code> to enable the component,
+ * <code>false</code> to disable it
+ */
+ public void setEnabled(boolean enabled)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setEnabled(enabled);
+ }
+
+ /**
+ * Sets the font of the component. This is called by
+ * {@link Component#setFont(Font)}.
+ *
+ * This is implemented to call setFont() on the Swing component.
+ *
+ * @param font the font to set
+ */
+ public void setFont(Font font)
+ {
+ peerFont = font;
+ if (swingComponent != null)
+ swingComponent.getJComponent().setFont(font);
+ }
+
+ /**
+ * Sets the foreground color of the component. This is called by
+ * {@link Component#setForeground(Color)}.
+ *
+ * This is implemented to call setForeground() on the Swing component.
+ *
+ * @param color the foreground color to set
+ */
+ public void setForeground(Color color)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setForeground(color);
+ }
+
+ /**
+ * Sets the visibility state of the component. This is called by
+ * {@link Component#setVisible(boolean)}.
+ *
+ * This is implemented to call setVisible() on the Swing component.
+ *
+ * @param visible <code>true</code> to make the component visible,
+ * <code>false</code> to make it invisible
+ */
+ public void setVisible(boolean visible)
+ {
+ if (visible)
+ show();
+ else
+ hide();
+ }
+
+ /**
+ * Makes the component visible. This is called by {@link Component#show()}.
+ *
+ * This is implemented to call setVisible(true) on the Swing component.
+ */
+ public void show()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setVisible(true);
+ }
+
+ /**
+ * Get the graphics configuration of the component. The color model
+ * of the component can be derived from the configuration.
+ *
+ * This is implemented to return the GraphicsConfiguration of the parent
+ * component. This will eventually call the toplevel component peer, which
+ * is expected to provide a real implementation.
+ *
+ * @return the graphics configuration of the component
+ */
+ public GraphicsConfiguration getGraphicsConfiguration()
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.getGraphicsConfiguration();
+ }
+
+ /**
+ * Part of an older API, no longer needed.
+ */
+ public void setEventMask(long mask)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns <code>true</code> if this component has been obscured,
+ * <code>false</code> otherwise. This will only work if
+ * {@link #canDetermineObscurity()} also returns <code>true</code>.
+ *
+ * This is not yet implemented.
+ *
+ * @return <code>true</code> if this component has been obscured,
+ * <code>false</code> otherwise.
+ */
+ public boolean isObscured()
+ {
+ return false;
+ }
+
+ /**
+ * Returns <code>true</code> if this component peer can determine if the
+ * component has been obscured, <code>false</code> otherwise.
+ *
+ * This is not yet implemented.
+ *
+ * @return <code>true</code> if this component peer can determine if the
+ * component has been obscured, <code>false</code> otherwise
+ */
+ public boolean canDetermineObscurity()
+ {
+ return false;
+ }
+
+ /**
+ * Coalesces the specified paint event.
+ *
+ * @param e the paint event
+ */
+ public void coalescePaintEvent(PaintEvent e)
+ {
+ synchronized (this)
+ {
+ Rectangle newRect = e.getUpdateRect();
+ if (paintArea == null)
+ paintArea = newRect;
+ else
+ Rectangle.union(paintArea, newRect, paintArea);
+ }
+ }
+
+ /**
+ * Updates the cursor. This is not yet implemented.
+ */
+ public void updateCursorImmediately()
+ {
+ // Nothing to do here yet.
+ }
+
+ /**
+ * Returns true, if this component can handle wheel scrolling,
+ * <code>false</code> otherwise.
+ *
+ * This is not yet implemented and returns <code>false</code>.
+ *
+ * @return true, if this component can handle wheel scrolling,
+ * <code>false</code> otherwise
+ */
+ public boolean handlesWheelScrolling()
+ {
+ return false;
+ }
+
+ /**
+ * A convenience method that creates a volatile image. The volatile
+ * image is created on the screen device on which this component is
+ * displayed, in the device's current graphics configuration.
+ *
+ * This is implemented to let the parent component peer create an image.
+ * This eventually ends up in the toplevel component peer, which is then
+ * responsible for creating the real image.
+ *
+ * @param width width of the image
+ * @param height height of the image
+ *
+ * @see VolatileImage
+ *
+ * @since 1.2
+ */
+ public VolatileImage createVolatileImage(int width, int height)
+ {
+ Component parent = awtComponent.getParent();
+ VolatileImage im = null;
+ if (parent != null)
+ {
+ ComponentPeer parentPeer = parent.getPeer();
+ im = parentPeer.createVolatileImage(width, height);
+ }
+ return im;
+ }
+
+ /**
+ * Create a number of image buffers that implement a buffering
+ * strategy according to the given capabilities.
+ *
+ * This is implemented to forward to the parent component peer. Eventually
+ * this ends up in the top level component peer, which is then responsible
+ * for doing the real work.
+ *
+ * @param numBuffers the number of buffers
+ * @param caps the buffering capabilities
+ *
+ * @throws AWTException if the specified buffering strategy is not
+ * implemented
+ *
+ * @since 1.2
+ */
+ public void createBuffers(int numBuffers, BufferCapabilities caps) throws AWTException
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ parentPeer.createBuffers(numBuffers, caps);
+ }
+
+ /**
+ * Return the back buffer of this component.
+ *
+ * This is implemented to forward to the parent. Eventually this ends
+ * up in the toplevel component, which is then responsible for providing
+ * a back buffer.
+ *
+ * @return the back buffer of this component.
+ *
+ * @since 1.2
+ */
+ public Image getBackBuffer()
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ return parentPeer.getBackBuffer();
+ }
+
+ /**
+ * Perform a page flip, leaving the contents of the back buffer in
+ * the specified state.
+ *
+ * This is implemented to forward to the parent. Eventually this ends
+ * up in the toplevel component, which is then responsible for doing the real
+ * work.
+ *
+ * @param contents the state in which to leave the back buffer
+ *
+ * @since 1.2
+ */
+ public void flip(FlipContents contents)
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ parentPeer.flip(contents);
+ }
+
+ /**
+ * Destroy the resources created by createBuffers.
+ *
+ * This is implemented to forward to the parent component peer. Eventually
+ * this ends up in the top level component peer, which is then responsible
+ * for doing the real work.
+ *
+ * @since 1.2
+ */
+ public void destroyBuffers()
+ {
+ Component parent = awtComponent.getParent();
+ ComponentPeer parentPeer = parent.getPeer();
+ parentPeer.destroyBuffers();
+ }
+
+ /**
+ * Get the bounds of this component peer.
+ *
+ * This is implemented to forward to the Swing component.
+ *
+ * @return component peer bounds
+ * @since 1.5
+ */
+ public Rectangle getBounds()
+ {
+ Rectangle retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getBounds();
+ else
+ retVal = new Rectangle();
+ return retVal;
+ }
+
+ /**
+ * Reparent this component under another container.
+ *
+ * @param parent
+ * @since 1.5
+ */
+ public void reparent(ContainerPeer parent)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Set the bounds of this component peer.
+ *
+ * This is implemented to forward to the swing component.
+ *
+ * @param x the new x co-ordinate
+ * @param y the new y co-ordinate
+ * @param width the new width
+ * @param height the new height
+ * @param z the new stacking level
+ * @since 1.5
+ */
+ public void setBounds(int x, int y, int width, int height, int z)
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().setBounds(x, y, width, height);
+ // FIXME: Somehow handle the Z order.
+ }
+
+ /**
+ * Check if this component supports being reparented.
+ *
+ * @return true if this component can be reparented,
+ * false otherwise.
+ * @since 1.5
+ */
+ public boolean isReparentSupported()
+ {
+ return true;
+ }
+
+
+ /**
+ * Layout this component peer.
+ *
+ * @since 1.5
+ */
+ public void layout()
+ {
+ if (swingComponent != null)
+ swingComponent.getJComponent().doLayout();
+ }
+
+ /**
+ * Triggers 'heavyweight' painting of the components. This usually calls
+ * paint() on the Swing component.
+ *
+ * @param g the graphics context to use for painting
+ * @param update wether we need to call update or paint on the AWT component
+ */
+ protected void peerPaint(Graphics g, boolean update)
+ {
+ peerPaintComponent(g);
+
+ Graphics userGraphics = g.create();
+ try{
+ if (update)
+ awtComponent.update(userGraphics);
+ else
+ awtComponent.paint(userGraphics);
+ } finally {
+ userGraphics.dispose();
+ }
+
+ }
+
+ /**
+ * Paints the actual 'heavyweight' swing component, if there is one
+ * associated to this peer.
+ *
+ * @param g the graphics to paint the component with
+ */
+ protected void peerPaintComponent(Graphics g)
+ {
+ // Paint the actual Swing component if this peer has one.
+ if (swingComponent != null)
+ swingComponent.getJComponent().paint(g);
+ }
+
+ /**
+ * Handles mouse events on the component. This is usually forwarded to the
+ * SwingComponent's processMouseEvent() method.
+ *
+ * @param e the mouse event
+ */
+ protected void handleMouseEvent(MouseEvent e)
+ {
+ if (swingComponent != null)
+ swingComponent.handleMouseEvent(e);
+ }
+
+ /**
+ * Handles mouse motion events on the component. This is usually forwarded
+ * to the SwingComponent's processMouseMotionEvent() method.
+ *
+ * @param e the mouse motion event
+ */
+ protected void handleMouseMotionEvent(MouseEvent e)
+ {
+ if (swingComponent != null)
+ swingComponent.handleMouseMotionEvent(e);
+ }
+
+ /**
+ * Handles key events on the component. This is usually forwarded to the
+ * SwingComponent's processKeyEvent() method.
+ *
+ * @param e the key event
+ */
+ protected void handleKeyEvent(KeyEvent e)
+ {
+ if (swingComponent != null)
+ swingComponent.handleKeyEvent(e);
+ }
+
+ /**
+ * Handles focus events on the component. This is usually forwarded to the
+ * SwingComponent's processFocusEvent() method.
+ *
+ * @param e the key event
+ */
+ protected void handleFocusEvent(FocusEvent e)
+ {
+ if (swingComponent != null)
+ swingComponent.handleFocusEvent(e);
+ }
+
+
+ /**
+ * Returns the AWT component for this peer.
+ *
+ * @return the AWT component for this peer
+ */
+ public Component getComponent()
+ {
+ return awtComponent;
+ }
+
+ public boolean requestFocus(Component lightweightChild, boolean temporary,
+ boolean focusedWindowChangeAllowed,
+ long time, sun.awt.CausedFocusEvent.Cause cause)
+ {
+ return true;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java
new file mode 100644
index 000000000..ca3adc4c7
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingContainerPeer.java
@@ -0,0 +1,378 @@
+/* SwingContainerPeer.java -- A Swing based peer for AWT containers
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import gnu.classpath.SystemProperties;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.ContainerPeer;
+import java.util.Iterator;
+import java.util.LinkedList;
+
+/**
+ * A peer for Container to be used with the Swing based AWT peers.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingContainerPeer
+ extends SwingComponentPeer
+ implements ContainerPeer
+{
+
+ /**
+ * Stores all heavyweight descendents of the container. This is used
+ * in {@link #peerPaintChildren(Graphics)}.
+ */
+ private LinkedList heavyweightDescendents;
+
+ /**
+ * The backbuffer used for painting UPDATE events.
+ */
+ private Image backbuffer;
+
+ /**
+ * Creates a new SwingContainerPeer.
+ *
+ * @param awtCont
+ */
+ public SwingContainerPeer(Container awtCont)
+ {
+ heavyweightDescendents = new LinkedList();
+ }
+
+ /**
+ * Registers a heavyweight descendent. This is then painted by
+ * {@link #peerPaintChildren(Graphics)}.
+ *
+ * @param comp the descendent to register
+ *
+ * @see #peerPaintChildren(Graphics)
+ * @see #removeHeavyweightDescendent(Component)
+ */
+ protected synchronized void addHeavyweightDescendent(Component comp)
+ {
+ heavyweightDescendents.add(comp);
+ focusOwner = null;
+ }
+
+ /**
+ * Unregisters a heavyweight descendent.
+ *
+ * @param comp the descendent to unregister
+ *
+ * @see #peerPaintChildren(Graphics)
+ * @see #addHeavyweightDescendent(Component)
+ */
+ protected synchronized void removeHeavyweightDescendent(Component comp)
+ {
+ heavyweightDescendents.remove(comp);
+ focusOwner = null;
+ }
+
+ /**
+ * Returns an array of all registered heavyweight descendents.
+ *
+ * @return all registered heavyweight descendents
+ */
+ protected Component[] getHeavyweightDescendents()
+ {
+ Component[] heavyweights = new Component[heavyweightDescendents.size()];
+ heavyweights = (Component[]) heavyweightDescendents.toArray(heavyweights);
+ return heavyweights;
+ }
+
+ /**
+ * Returns the insets of the container.
+ *
+ * This is implemented to return the insets of the Swing container.
+ *
+ * @return the insets of the container
+ */
+ public Insets insets()
+ {
+ Insets retVal;
+ if (swingComponent != null)
+ retVal = swingComponent.getJComponent().getInsets();
+ else
+ retVal = new Insets(0, 0, 0, 0);
+ return retVal;
+ }
+
+ /**
+ * Returns the insets of the container.
+ *
+ * This is implemented to return the insets of the Swing container.
+ *
+ * @return the insets of the container
+ */
+ public Insets getInsets()
+ {
+ return insets();
+ }
+
+ /**
+ * Called before the validation of this containers begins.
+ */
+ public void beginValidate()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Called after the validation of this containers ended.
+ */
+ public void endValidate()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Called before the layout of this containers begins.
+ */
+ public void beginLayout()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Called after the layout of this containers ended.
+ */
+ public void endLayout()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Returns <code>false</code> unconditionally. This method is not used at
+ * the moment.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isPaintPending()
+ {
+ return false;
+ }
+
+ /**
+ * Returns <code>false</code> unconditionally. This method is not used at
+ * the moment.
+ *
+ * @return <code>false</code>
+ */
+ public boolean isRestackSupported()
+ {
+ return false;
+ }
+
+ /**
+ * This method is not used at the moment.
+ */
+ public void cancelPendingPaint(int x, int y, int width, int height)
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * This method is not used at the moment.
+ */
+ public void restack()
+ {
+ // Nothing to do here.
+ }
+
+ /**
+ * Performs the super behaviour (call peerPaintComponent() and
+ * awtComponent.paint()), and forwards the paint request to the heavyweight
+ * descendents of the container.
+ */
+ protected void peerPaint(Graphics g, boolean update)
+ {
+ if (isDoubleBuffering())
+ {
+ int width = awtComponent.getWidth();
+ int height = awtComponent.getHeight();
+ if (backbuffer == null
+ || backbuffer.getWidth(awtComponent) < width
+ || backbuffer.getHeight(awtComponent) < height)
+ backbuffer = awtComponent.createImage(width, height);
+ Graphics g2 = backbuffer.getGraphics();
+ Rectangle clip = g.getClipRect();
+ try
+ {
+ g2.setClip(clip);
+ super.peerPaint(g2, update);
+ peerPaintChildren(g2);
+ }
+ finally
+ {
+ g2.dispose();
+ }
+ g.drawImage(backbuffer, 0, 0, awtComponent);
+ }
+ else
+ {
+ super.peerPaint(g, update);
+ peerPaintChildren(g);
+ }
+ }
+
+ /**
+ * Determines if we should do double buffering or not.
+ *
+ * @return if we should do double buffering or not
+ */
+ private boolean isDoubleBuffering()
+ {
+ Object prop =
+ SystemProperties.getProperty("gnu.awt.swing.doublebuffering", "false");
+ return prop.equals("true");
+ }
+
+ /**
+ * Paints any heavyweight child components.
+ *
+ * @param g the graphics to use for painting
+ */
+ protected synchronized void peerPaintChildren(Graphics g)
+ {
+ // TODO: Is this the right painting order?
+ for (Iterator i = heavyweightDescendents.iterator(); i.hasNext();)
+ {
+ Component child = (Component) i.next();
+ ComponentPeer peer = child.getPeer();
+
+ if (peer instanceof SwingComponentPeer && child.isVisible())
+ {
+ // TODO: The translation here doesn't work for deeper
+ // nested children. Fix this!
+ Graphics g2 = g.create(child.getX(), child.getY(),
+ child.getWidth(), child.getHeight());
+ try
+ {
+ // update() is only called for the topmost component if
+ // necessary, all other components only get paint() called.
+ ((SwingComponentPeer) peer).peerPaint(g2, false);
+ }
+ finally
+ {
+ g2.dispose();
+ }
+ }
+ }
+ }
+
+ /**
+ * Handles mouse events by dispatching it to the correct component.
+ *
+ * @param ev the mouse event
+ */
+ protected void handleMouseEvent(MouseEvent ev)
+ {
+ Component comp = awtComponent.getComponentAt(ev.getPoint());
+ if(comp == null) comp = awtComponent;
+ ComponentPeer peer = comp.getPeer();
+ if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
+ {
+ ev.translatePoint(comp.getX(), comp.getY());
+ ev.setSource(comp);
+ ((SwingComponentPeer) peer).handleMouseEvent(ev);
+ }
+ }
+
+ /**
+ * Handles mouse events by dispatching it to the correct component.
+ *
+ * @param ev the mouse event
+ */
+ protected void handleMouseMotionEvent(MouseEvent ev)
+ {
+ Component comp = awtComponent.getComponentAt(ev.getPoint());
+ if (comp != null)
+ {
+ ComponentPeer peer = comp.getPeer();
+ if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
+ {
+ ev.translatePoint(comp.getX(), comp.getY());
+ ((SwingComponentPeer) peer).handleMouseMotionEvent(ev);
+ }
+ }
+ }
+
+ /**
+ * Handles key events on the component. This is usually forwarded to the
+ * SwingComponent's processKeyEvent() method.
+ *
+ * @param e the key event
+ */
+ protected void handleKeyEvent(KeyEvent e)
+ {
+ Component owner = getFocusOwner();
+ if(owner != null)
+ owner.getPeer().handleEvent(e);
+ else
+ super.handleKeyEvent(e);
+ }
+
+ private Component focusOwner = null;
+
+ private Component getFocusOwner()
+ {
+ if(focusOwner == null)
+ {
+ for(Iterator iter=heavyweightDescendents.iterator(); iter.hasNext();)
+ {
+ Component child = (Component) iter.next();
+ if(child.isFocusable())
+ {
+ focusOwner = child;
+ break;
+ }
+ }
+ }
+ return focusOwner;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingFramePeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingFramePeer.java
new file mode 100644
index 000000000..56c7417cd
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingFramePeer.java
@@ -0,0 +1,197 @@
+/* SwingFramePeer.java -- An abstract Swing based peer for AWT frames
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.MenuBar;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.FramePeer;
+
+/**
+ * An abstract base class for FramePeer implementations based on Swing.
+ * This class provides the ability to display and handle AWT MenuBars that
+ * are based on Swing.
+ *
+ * As a minimum, a subclass must implement all the remaining abstract methods
+ * as well as the following methods:
+ * <ul>
+ * <li>{@link ComponentPeer#getLocationOnScreen()}</li>
+ * <li>{@link ComponentPeer#getGraphics()}</li>
+ * <li>{@link ComponentPeer#createImage(int, int)}</li>
+ * </ul>
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public abstract class SwingFramePeer
+ extends SwingWindowPeer
+ implements FramePeer
+{
+ /**
+ * The menu bar to display.
+ */
+ SwingMenuBarPeer menuBar = null;
+
+ /**
+ * Creates a new SwingFramePeer.
+ *
+ * @param frame the frame
+ */
+ public SwingFramePeer(Frame frame)
+ {
+ super(frame);
+ }
+
+ /**
+ * Sets the menu bar to display in this frame.
+ *
+ * @param mb the menu bar to set
+ */
+ public void setMenuBar(MenuBar mb)
+ {
+ menuBar = (SwingMenuBarPeer) mb.getPeer();
+ menuBar.setFramePeer(this);
+ menuBar.setWidth(awtComponent.getWidth());
+ }
+
+ /**
+ * Triggers 'heavyweight' painting of the frame. This will paint a menu bar
+ * if present as well as the child components of this frame.
+ *
+ * @param g the graphics context to use for painting
+ */
+ protected void peerPaintComponent(Graphics g)
+ {
+ super.peerPaintComponent(g);
+ if (menuBar != null)
+ menuBar.peerPaint(g);
+ }
+
+ /**
+ * Sets the size and location of this frame. This resizes the menubar to fit
+ * within the frame.
+ *
+ * @param x the X coordinate of the screen location
+ * @param y the Y coordinate of the screen location
+ * @param w the width of the frame
+ * @param h the height of the frame
+ */
+ public void setBounds(int x, int y, int w, int h)
+ {
+ super.setBounds(x, y, w, h);
+ if (menuBar != null)
+ menuBar.setWidth(w);
+ }
+
+ /**
+ * Calculates the insets of this frame peer. This fetches the insets
+ * from the superclass and adds the insets of the menubar if one is present.
+ *
+ * @return the insets of the frame
+ */
+ public Insets getInsets()
+ {
+ Insets insets = super.getInsets();
+ if (menuBar != null)
+ insets.top += menuBar.getHeight();
+ return insets;
+ }
+
+ /**
+ * Returns the location of the menu on the screen. This is needed internally
+ * by the {@link SwingMenuBarPeer} in order to determine its screen location.
+ *
+ * @return the location of the menu on the screen
+ */
+ public Point getMenuLocationOnScreen()
+ {
+ Insets i = super.getInsets();
+ return new Point(i.top, i.left);
+ }
+
+ /**
+ * Overridden to provide the ability to handle menus.
+ *
+ * @param ev the mouse event
+ */
+ protected void handleMouseEvent(MouseEvent ev)
+ {
+ Point p = ev.getPoint();
+ Insets i = super.getInsets();
+ if (menuBar != null)
+ {
+ int menuHeight = menuBar.getHeight();
+ if (p.y >= i.top && p.y <= i.top + menuHeight)
+ menuBar.handleMouseEvent(ev);
+ else
+ {
+ ev.translatePoint(0, -menuHeight);
+ super.handleMouseMotionEvent(ev);
+ }
+ }
+
+ super.handleMouseEvent(ev);
+ }
+
+ /**
+ * Overridden to provide the ability to handle menus.
+ *
+ * @param ev the mouse event
+ */
+ protected void handleMouseMotionEvent(MouseEvent ev)
+ {
+ Point p = ev.getPoint();
+ Insets i = super.getInsets();
+ if (menuBar != null)
+ {
+ int menuHeight = menuBar.getHeight();
+ if (p.y >= i.top && p.y <= i.top + menuHeight)
+ menuBar.handleMouseMotionEvent(ev);
+ else
+ {
+ ev.translatePoint(0, -menuHeight);
+ super.handleMouseMotionEvent(ev);
+ }
+ }
+
+ super.handleMouseMotionEvent(ev);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java
new file mode 100644
index 000000000..5c979d613
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingLabelPeer.java
@@ -0,0 +1,242 @@
+/* SwingLabelPeer.java -- A Swing based peer for AWT labels
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Label;
+import java.awt.Point;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.LabelPeer;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+
+
+/**
+ * A Label peer based on {@link JLabel}.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingLabelPeer
+ extends SwingComponentPeer
+ implements LabelPeer
+{
+
+ /**
+ * A spezialized Swing label used to paint the label for the AWT Label.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingLabel
+ extends JLabel
+ implements SwingComponent
+ {
+ Label label;
+
+
+ SwingLabel(Label label)
+ {
+ this.label = label;
+ }
+
+ /**
+ * Returns this label.
+ *
+ * @return <code>this</code>
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to
+ * <code>processMouseMotionEvent()</code>.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to <code>processKeyEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ processKeyEvent(ev);
+ }
+
+ /**
+ * Handles focus events by forwarding it to
+ * <code>processFocusEvent()</code>.
+ *
+ * @param ev the Focus event
+ */
+ public void handleFocusEvent(FocusEvent ev)
+ {
+ processFocusEvent(ev);
+ }
+
+ /**
+ * Overridden so that this method returns the correct value even without a
+ * peer.
+ *
+ * @return the screen location of the button
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingLabelPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value for the
+ * swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (label != null)
+ retVal = label.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingLabelPeer.this.createImage(w, h);
+ }
+
+ public Graphics getGraphics()
+ {
+ return SwingLabelPeer.this.getGraphics();
+ }
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (label != null)
+ par = label.getParent();
+ return par;
+ }
+ }
+
+ /**
+ * Creates a new <code>SwingLabelPeer</code> for the specified AWT label.
+ *
+ * @param label the AWT label
+ */
+ public SwingLabelPeer(Label label)
+ {
+ super();
+ SwingLabel swingLabel = new SwingLabel(label);
+ swingLabel.setText(label.getText());
+ swingLabel.setOpaque(true);
+ init(label, swingLabel);
+ setAlignment(label.getAlignment());
+ }
+
+ /**
+ * Sets the text of the label. This is implemented to set the text on the
+ * Swing label.
+ *
+ * @param text the text to be set
+ */
+ public void setText(String text)
+ {
+ ((JLabel) swingComponent.getJComponent()).setText(text);
+ }
+
+ /**
+ * Sets the horizontal alignment of the label. This is implemented to
+ * set the alignment on the Swing label.
+ *
+ * @param alignment the horizontal alignment
+ *
+ * @see Label#LEFT
+ * @see Label#RIGHT
+ * @see Label#CENTER
+ */
+ public void setAlignment(int alignment)
+ {
+ JLabel swingLabel = (JLabel) swingComponent.getJComponent();
+ switch (alignment)
+ {
+ case Label.RIGHT:
+ swingLabel.setHorizontalAlignment(JLabel.RIGHT);
+ break;
+ case Label.CENTER:
+ swingLabel.setHorizontalAlignment(JLabel.CENTER);
+ break;
+ case Label.LEFT:
+ default:
+ swingLabel.setHorizontalAlignment(JLabel.LEFT);
+ break;
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingListPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingListPeer.java
new file mode 100644
index 000000000..cf766fd4f
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingListPeer.java
@@ -0,0 +1,364 @@
+/* SwingListPeer.java -- A Swing based peer for AWT lists
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.List;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.peer.ListPeer;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JComponent;
+import javax.swing.JList;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
+
+public class SwingListPeer
+ extends SwingComponentPeer
+ implements ListPeer
+{
+
+ /**
+ * A spezialized Swing scroller used to hold the list.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingList
+ extends JScrollPane
+ implements SwingComponent
+ {
+
+ SwingList(Component comp)
+ {
+ super(comp, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ }
+
+ /**
+ * Returns this label.
+ *
+ * @return <code>this</code>
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ dispatchEvent(ev);
+ }
+
+ /**
+ * Force lightweight mouse dispatching.
+ */
+ public boolean isLightweight()
+ {
+ return false;
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to
+ * <code>processMouseMotionEvent()</code>.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to <code>processKeyEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ processKeyEvent(ev);
+ }
+
+ /**
+ * Handles focus events by forwarding it to <code>processFocusEvent()</code>.
+ *
+ * @param ev the Focus event
+ */
+ public void handleFocusEvent(FocusEvent ev)
+ {
+ processFocusEvent(ev);
+ }
+
+
+ /**
+ * Overridden so that this method returns the correct value even without a
+ * peer.
+ *
+ * @return the screen location of the button
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingListPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value for the
+ * swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (SwingListPeer.this.awtComponent != null)
+ retVal = SwingListPeer.this.awtComponent.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingListPeer.this.createImage(w, h);
+ }
+
+ public Graphics getGraphics()
+ {
+ return SwingListPeer.this.getGraphics();
+ }
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (SwingListPeer.this.awtComponent != null)
+ par = SwingListPeer.this.awtComponent.getParent();
+ return par;
+ }
+ }
+
+ /**
+ * The actual Swing JList.
+ */
+ private JList jList;
+
+ private DefaultListModel listModel;
+
+ public SwingListPeer(List list)
+ {
+ super();
+ listModel = new DefaultListModel();
+ jList = new JList(listModel);
+ SwingList swingList = new SwingList(jList);
+ init(list, swingList);
+
+ // Pull over the items from the list.
+ String[] items = list.getItems();
+ for (int i = 0 ; i < items.length; i++)
+ addItem(items[i], i);
+ }
+
+ public void add(String item, int index)
+ {
+ if (listModel != null)
+ listModel.add(index, item);
+ }
+
+ public void addItem(String item, int index)
+ {
+ if (listModel != null)
+ listModel.add(index, item);
+ }
+
+ public void clear()
+ {
+ if (listModel != null)
+ listModel.clear();
+ }
+
+ public void delItems(int startIndex, int endIndex)
+ {
+ if (listModel != null)
+ listModel.removeRange(startIndex, endIndex);
+ }
+
+ public void deselect(int index)
+ {
+ if (jList != null)
+ {
+ jList.getSelectionModel().removeSelectionInterval(index, index);
+ }
+ }
+
+ public Dimension getMinimumSize(int s)
+ {
+ Dimension d = null;
+ if (jList != null)
+ {
+ d = jList.getComponent(s).getMinimumSize();
+ }
+ return d;
+ }
+
+ public Dimension getPreferredSize(int s)
+ {
+ Dimension d = null;
+ if (jList != null)
+ {
+ d = jList.getComponent(s).getPreferredSize();
+ }
+ return d;
+ }
+
+ public int[] getSelectedIndexes()
+ {
+ int[] sel = null;
+ if (jList != null)
+ {
+ sel = jList.getSelectedIndices();
+ }
+ return sel;
+ }
+
+ public void makeVisible(int index)
+ {
+ if (jList != null)
+ {
+ Component comp = jList.getComponent(index);
+ jList.scrollRectToVisible(comp.getBounds());
+ }
+ }
+
+ public Dimension minimumSize(int s)
+ {
+ Dimension d = null;
+ if (jList != null)
+ {
+ d = jList.getComponent(s).getMinimumSize();
+ }
+ return d;
+ }
+
+ public Dimension preferredSize(int s)
+ {
+ Dimension d = null;
+ if (jList != null)
+ {
+ d = jList.getComponent(s).getPreferredSize();
+ }
+ return d;
+ }
+
+ public void removeAll()
+ {
+ if (jList != null)
+ {
+ jList.removeAll();
+ }
+ }
+
+ public void select(int index)
+ {
+ if (jList != null)
+ {
+ jList.setSelectedIndex(index);
+ }
+ }
+
+ public void setMultipleMode(boolean multi)
+ {
+ if (jList != null)
+ {
+ jList.setSelectionMode(multi
+ ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
+ : ListSelectionModel.SINGLE_SELECTION);
+ }
+ }
+
+ public void setMultipleSelections(boolean multi)
+ {
+ if (jList != null)
+ {
+ jList.setSelectionMode(multi
+ ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION
+ : ListSelectionModel.SINGLE_SELECTION);
+ }
+ }
+
+ public void reshape(int x, int y, int width, int height)
+ {
+ if (swingComponent != null)
+ {
+ swingComponent.getJComponent().setBounds(x, y, width, height);
+ swingComponent.getJComponent().validate();
+ }
+ }
+
+ protected void peerPaint(Graphics g, boolean update)
+ {
+ super.peerPaint(g, update);
+ jList.doLayout();
+ jList.list();
+
+ Rectangle r = getBounds();
+ g.setColor(Color.RED);
+ g.drawRect(r.x, r.y, r.width, r.height);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuBarPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuBarPeer.java
new file mode 100644
index 000000000..0033efb02
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuBarPeer.java
@@ -0,0 +1,295 @@
+/* SwingMenuBarPeer.java -- A Swing based peer for AWT menu bars
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Container;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import java.awt.peer.MenuBarPeer;
+
+import javax.swing.JMenuBar;
+
+/**
+ * A Swing based peer for the AWT menu bar. This is a little bit different from
+ * the other peers, since the AWT MenuBar is not derived from the AWT
+ * component.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingMenuBarPeer
+ implements MenuBarPeer
+{
+
+ /**
+ * The AWT menu bar.
+ */
+ MenuBar awtMenuBar;
+
+ /**
+ * The Swing menu bar.
+ */
+ SwingMenuBar menuBar;
+
+ /**
+ * The peer of the frame that contains this menu bar.
+ */
+ SwingFramePeer framePeer;
+
+ /**
+ * A specialized JMenuBar that can be used as 'backend' for AWT MenuBars.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingMenuBar
+ extends JMenuBar
+ {
+ /**
+ * Overridden in order to provide a parent frame for this menu bar. The
+ * menu bar still is not inside the component hierarchy, we are faking
+ * here.
+ */
+ public Container getParent()
+ {
+ Container result = null;
+ if (framePeer != null)
+ result = (Container) framePeer.awtComponent;
+ return result;
+ }
+
+ /**
+ * Unconditionally returns <code>true</code>, since we assume that when the
+ * menubar has a peer, it must be showing.
+ *
+ * @return <code>true</code>
+ */
+ public boolean isShowing()
+ {
+ // FIXME: This might be wrong. Maybe find a better way to do that.
+ return true;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Determines the menubar's screen location by asking the SwingFramePeer
+ * for it.
+ *
+ * @return the screen location of the menu bar
+ */
+ public Point getLocationOnScreen()
+ {
+ return framePeer.getMenuLocationOnScreen();
+ }
+ }
+
+ /**
+ * Creates a new <code>SwingMenuBarPeer</code> instance.
+ *
+ * @param awtMenuBar the AWT menu bar
+ */
+ public SwingMenuBarPeer(MenuBar awtMenuBar)
+ {
+ this.awtMenuBar = awtMenuBar;
+ menuBar = new SwingMenuBar();
+ menuBar.setDoubleBuffered(false);
+ // Add all the menus that are already in the MenuBar.
+ for (int i = 0; i < awtMenuBar.getMenuCount(); i++)
+ {
+ Menu menu = awtMenuBar.getMenu(i);
+ menu.addNotify();
+ addMenu(awtMenuBar.getMenu(i));
+ }
+ }
+
+ /**
+ * Sets the <code>SwingFramePeer</code> of the frame that holds this menu.
+ *
+ * @param peer the <code>SwingFramePeer</code> to set
+ */
+ public void setFramePeer(SwingFramePeer peer)
+ {
+ framePeer = peer;
+ }
+
+ /**
+ * Adds a menu to the menu bar.
+ *
+ * @param m the menu to add
+ */
+ public void addMenu(Menu m)
+ {
+ SwingMenuPeer menuPeer = (SwingMenuPeer) m.getPeer();
+ menuBar.add(menuPeer.menu);
+ }
+
+ /**
+ * Adds a help menu to the menu bar.
+ *
+ * @param menu the menu to add
+ */
+ public void addHelpMenu(Menu menu)
+ {
+ // FIXME: We should manage the help menu differently, so that it always
+ // appears at the rightmost position.
+ SwingMenuPeer menuPeer = (SwingMenuPeer) menu.getPeer();
+ menuBar.add(menuPeer.menu);
+ }
+
+ /**
+ * Removes the menu with the specified index.
+ *
+ * @param index the index of the menu to remove
+ */
+ public void delMenu(int index)
+ {
+ menuBar.remove(index);
+ }
+
+ /**
+ * Disposes this peer. This releases any reference to the AWT and Swing
+ * components.
+ */
+ public void dispose()
+ {
+ menuBar = null;
+ awtMenuBar = null;
+ }
+
+ /**
+ * Sets a font for the menu bar.
+ *
+ * @param font the font to set
+ */
+ public void setFont(Font font)
+ {
+ menuBar.setFont(font);
+ }
+
+ /**
+ * Sets the width of the menu bar. This is called from the top level
+ * component peers to adjust the width of the menubar when their sizes
+ * change.
+ *
+ * @param w the width to set
+ */
+ public void setWidth(int w)
+ {
+ menuBar.setSize(w, menuBar.getPreferredSize().height);
+ menuBar.doLayout();
+ }
+
+ /**
+ * Paints the menu bar.
+ *
+ * @param g the graphics context to use for painting
+ */
+ public void peerPaint(Graphics g)
+ {
+ menuBar.paint(g);
+ }
+
+ /**
+ * Determines the height of the menubar.
+ *
+ * @return the height of the menu bar
+ */
+ public int getHeight()
+ {
+ return menuBar.getPreferredSize().height;
+ }
+
+ /**
+ * Handles mouse events.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ Point point = ev.getPoint();
+ for (int i = 0; i < awtMenuBar.getMenuCount(); i++)
+ {
+ Menu menu = awtMenuBar.getMenu(i);
+ SwingMenuPeer peer = (SwingMenuPeer) menu.getPeer();
+ int x1 = peer.getX();
+ int x2 = x1 + peer.getWidth();
+ if (point.x >= x1 && point.x <= x2)
+ {
+ ev.translatePoint(peer.getX(), peer.getY());
+ peer.handleMouseEvent(ev);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Handles mouse motion events.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ Point point = ev.getPoint();
+ for (int i = 0; i < awtMenuBar.getMenuCount(); i++)
+ {
+ Menu menu = awtMenuBar.getMenu(i);
+ SwingMenuPeer peer = (SwingMenuPeer) menu.getPeer();
+ int x1 = peer.getX();
+ int x2 = x1 + peer.getWidth();
+ if (point.x >= x1 && point.x <= x2)
+ {
+ ev.translatePoint(peer.getX(), peer.getY());
+ peer.handleMouseMotionEvent(ev);
+ break;
+ }
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuItemPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuItemPeer.java
new file mode 100644
index 000000000..721b3349f
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuItemPeer.java
@@ -0,0 +1,157 @@
+/* SwingMenuItemPeer.java -- A Swing based peer for AWT menu items
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Font;
+import java.awt.MenuItem;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.peer.MenuItemPeer;
+
+import javax.swing.JMenuItem;
+
+/**
+ * A Swing based peer for the AWT MenuItem.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingMenuItemPeer
+ implements MenuItemPeer
+{
+ /**
+ * The AWT menu item.
+ */
+ MenuItem awtMenuItem;
+
+ /**
+ * The Swing menu item.
+ */
+ JMenuItem menuItem;
+
+ /**
+ * Receives ActionEvents from the Swing menu item and forwards them
+ * to the ActionListeners of the AWT MenuItem.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingMenuItemListener implements ActionListener
+ {
+
+ /**
+ * Receives notification when the action has been performed.
+ *
+ * @param event the action event
+ */
+ public void actionPerformed(ActionEvent event)
+ {
+ event.setSource(awtMenuItem);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
+ }
+
+ }
+
+ /**
+ * Creates a new instance of <code>SwingMenuItemPeer</code>.
+ *
+ * @param awtMenuItem the AWT menu item
+ */
+ public SwingMenuItemPeer(MenuItem awtMenuItem)
+ {
+ this.awtMenuItem = awtMenuItem;
+ menuItem = new JMenuItem(awtMenuItem.getLabel());
+ menuItem.addActionListener(new SwingMenuItemListener());
+ }
+
+ /**
+ * Disables the menu item.
+ */
+ public void disable()
+ {
+ menuItem.setEnabled(false);
+ }
+
+ /**
+ * Enables the menu item.
+ */
+ public void enable()
+ {
+ menuItem.setEnabled(true);
+ }
+
+ /**
+ * Sets the enabled state to <code>enabled</code>.
+ *
+ * @param enabled if the menu item should be enabled or not
+ */
+ public void setEnabled(boolean enabled)
+ {
+ menuItem.setEnabled(enabled);
+ }
+
+ /**
+ * Sets the label for the menu item.
+ *
+ * @param text the label to set
+ */
+ public void setLabel(String text)
+ {
+ menuItem.setText(text);
+ }
+
+ /**
+ * Disposes the menu item. This releases any reference to the Swing and AWT
+ * menu item.
+ */
+ public void dispose()
+ {
+ menuItem = null;
+ awtMenuItem = null;
+ }
+
+ /**
+ * Sets the font for this menu item.
+ *
+ * @param font the font to set
+ */
+ public void setFont(Font font)
+ {
+ menuItem.setFont(font);
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuPeer.java
new file mode 100644
index 000000000..afe20616d
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingMenuPeer.java
@@ -0,0 +1,284 @@
+/* SwingMenuPeer.java -- A Swing based peer for AWT menus
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Font;
+import java.awt.Menu;
+import java.awt.MenuItem;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import java.awt.peer.MenuPeer;
+
+import javax.swing.JMenu;
+
+/**
+ * A Swing based peer for the AWT menu.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingMenuPeer
+ implements MenuPeer
+{
+
+ /**
+ * The AWT menu.
+ */
+ Menu awtMenu;
+
+ /**
+ * The Swing menu.
+ */
+ SwingMenu menu;
+
+ /**
+ * A specialized JMenu that can be used as 'backend' for an AWT menu.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingMenu
+ extends JMenu
+ {
+
+ /**
+ * Unconditionally returns <code>true</code>, since we assume that when the
+ * menu has a peer, it must be showing.
+ *
+ * @return <code>true</code>
+ */
+ public boolean isShowing()
+ {
+ // FIXME: This might be wrong. Maybe find a better way to do that.
+ return true;
+ }
+
+ /**
+ * Overridden so that we can provide a location even without a real peer
+ * attached.
+ *
+ * @return the screen location of this menu
+ */
+ public Point getLocationOnScreen()
+ {
+ Point parentLoc = getParent().getLocationOnScreen();
+ parentLoc.x += getX();
+ parentLoc.y += getY();
+ return parentLoc;
+ }
+
+ /**
+ * Handles mouse events by forwarding them to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse events by forwarding them to
+ * <code>processMouseMotionEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseMotionEvent(ev);
+ }
+ }
+
+ /**
+ * Creates a new <code>SwingMenuPeer</code> instance.
+ *
+ * @param awtMenu the AWT menu
+ */
+ public SwingMenuPeer(Menu awtMenu)
+ {
+ this.awtMenu = awtMenu;
+ menu = new SwingMenu();
+ menu.setDoubleBuffered(false);
+ menu.setText(awtMenu.getLabel());
+ for (int i = 0; i < awtMenu.getItemCount(); i++)
+ {
+ MenuItem item = awtMenu.getItem(i);
+ item.addNotify();
+ SwingMenuItemPeer peer = (SwingMenuItemPeer) item.getPeer();
+ menu.add(peer.menuItem);
+ }
+ }
+
+ /**
+ * Adds a menu item to this menu.
+ *
+ * @param item the menu item to add
+ */
+ public void addItem(MenuItem item)
+ {
+ SwingMenuItemPeer menuItemPeer = (SwingMenuItemPeer) item.getPeer();
+ menu.add(menuItemPeer.menuItem);
+ }
+
+ /**
+ * Adds a separator to the menu.
+ */
+ public void addSeparator()
+ {
+ menu.addSeparator();
+ }
+
+ /**
+ * Removes a menu item from the menu.
+ *
+ * @param index the index of the menu item to remove
+ */
+ public void delItem(int index)
+ {
+ menu.remove(index);
+ }
+
+ /**
+ * Disables the menu.
+ */
+ public void disable()
+ {
+ menu.setEnabled(false);
+ }
+
+ /**
+ * Enables the menu.
+ */
+ public void enable()
+ {
+ menu.setEnabled(true);
+ }
+
+ /**
+ * Sets the enabled state of the menu to <code>enabled</code>.
+ *
+ * @param enabled if the menu should be enabled or not
+ */
+ public void setEnabled(boolean enabled)
+ {
+ menu.setEnabled(enabled);
+ }
+
+ /**
+ * Sets the label of the menu.
+ *
+ * @param text the label to set
+ */
+ public void setLabel(String text)
+ {
+ menu.setText(text);
+ }
+
+ /**
+ * Releases any reference to the AWT and Swing menu instances.
+ */
+ public void dispose()
+ {
+ menu = null;
+ awtMenu = null;
+ }
+
+ /**
+ * Sets the font for the menu.
+ *
+ * @param font the font to set
+ */
+ public void setFont(Font font)
+ {
+ menu.setFont(font);
+ }
+
+ /**
+ * Handles mouse events by forwarding them to the Swing menu.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ menu.handleMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse motion events by forwarding them to the Swing menu.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ menu.handleMouseMotionEvent(ev);
+ }
+
+ /**
+ * Returns the X coordinate of the upper left corner of the menu. This is
+ * used internally by the SwingMenuBarPeer.
+ *
+ * @return the X coordinate of the upper left corner of the menu
+ */
+ int getX()
+ {
+ return menu.getX();
+ }
+
+ /**
+ * Returns the width of the menu. This is used internally by the
+ * SwingMenuBarPeer.
+ *
+ * @return the X coordinate of the upper left corner of the menu
+ */
+ int getWidth()
+ {
+ return menu.getWidth();
+ }
+
+ /**
+ * Returns the Y coordinate of the upper left corner of the menu. This is
+ * used internally by the SwingMenuBarPeer.
+ *
+ * @return the X coordinate of the upper left corner of the menu
+ */
+ public int getY()
+ {
+ return menu.getY();
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java
new file mode 100644
index 000000000..37c6dbc7a
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingPanelPeer.java
@@ -0,0 +1,67 @@
+/* SwingPanelPeer.java -- A PanelPeer based on Swing
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Panel;
+import java.awt.peer.PanelPeer;
+
+/**
+ * A panel peer based on Swing.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+// TODO: Maybe base implementation on JPanel. However, this doesn't seem
+// necessary, but might be good for more consistent Look.
+public class SwingPanelPeer
+ extends SwingContainerPeer
+ implements PanelPeer
+{
+
+ /**
+ * Creates a new instance of <code>SwingPanelPeer</code> for the specified
+ * AWT panel.
+ *
+ * @param panel the AWT panel
+ */
+ public SwingPanelPeer(Panel panel)
+ {
+ super(panel);
+ init(panel, null);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingTextAreaPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingTextAreaPeer.java
new file mode 100644
index 000000000..d56e950ec
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingTextAreaPeer.java
@@ -0,0 +1,487 @@
+/* SwingTextAreaPeer.java -- A Swing based peer for AWT textareas
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.TextArea;
+import java.awt.event.ComponentEvent;
+import java.awt.event.FocusEvent;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.InputMethodEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.im.InputMethodRequests;
+import java.awt.peer.TextAreaPeer;
+
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JViewport;
+import javax.swing.text.BadLocationException;
+
+public class SwingTextAreaPeer
+ extends SwingComponentPeer
+ implements TextAreaPeer
+{
+
+ /**
+ * A spezialized Swing scroller used to hold the textarea.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingScrollPane
+ extends JScrollPane
+ implements SwingComponent
+ {
+
+ SwingTextArea textArea;
+
+ SwingScrollPane(SwingTextArea textArea)
+ {
+ super(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+
+ this.textArea = textArea;
+ }
+
+ /**
+ * Returns this label.
+ *
+ * @return <code>this</code>
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to
+ * <code>processMouseEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ JViewport viewPort = getViewport();
+ if(viewPort.contains(ev.getPoint()))
+ {
+ ev.setSource(textArea);
+ textArea.dispatchEvent(ev);
+ }
+ else
+ {
+ ev.setSource(this);
+ this.dispatchEvent(ev);
+ }
+ }
+
+ /**
+ * Force lightweight mouse dispatching.
+ */
+ public boolean isLightweight()
+ {
+ return false;
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to
+ * <code>processMouseMotionEvent()</code>.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ textArea.processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to <code>processKeyEvent()</code>.
+ *
+ * @param ev the mouse event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ textArea.processKeyEvent(ev);
+ }
+
+ /**
+ * Handles focus events by forwarding it to
+ * <code>processFocusEvent()</code>.
+ *
+ * @param ev the Focus event
+ */
+ public void handleFocusEvent(FocusEvent ev)
+ {
+ textArea.processFocusEvent(ev);
+ }
+
+ /**
+ * Overridden so that this method returns the correct value even without a
+ * peer.
+ *
+ * @return the screen location of the button
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingTextAreaPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value for the
+ * swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (SwingTextAreaPeer.this.awtComponent != null)
+ retVal = SwingTextAreaPeer.this.awtComponent.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingTextAreaPeer.this.createImage(w, h);
+ }
+
+ public Graphics getGraphics()
+ {
+ return SwingTextAreaPeer.this.getGraphics();
+ }
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (SwingTextAreaPeer.this.awtComponent != null)
+ par = SwingTextAreaPeer.this.awtComponent.getParent();
+ return par;
+ }
+
+ public void requestFocus() {
+ SwingTextAreaPeer.this.requestFocus(awtComponent, false, true, 0);
+ }
+
+ public boolean requestFocus(boolean temporary) {
+ return SwingTextAreaPeer.this.requestFocus(awtComponent, temporary,
+ true, 0);
+ }
+
+ }
+
+ private class SwingTextArea extends JTextArea
+ {
+ /**
+ * Make this method accessible in this Package.
+ */
+ protected final void processComponentKeyEvent(KeyEvent e)
+ {
+ super.processComponentKeyEvent(e);
+ }
+
+ /**
+ * Make this method accessible in this Package.
+ */
+ protected final void processMouseMotionEvent(MouseEvent ev)
+ {
+ super.processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Make this method accessible in this Package.
+ */
+ protected final void processComponentEvent(ComponentEvent e)
+ {
+ super.processComponentEvent(e);
+ }
+
+ /**
+ * Make this method accessible in this Package.
+ */
+ protected final void processFocusEvent(FocusEvent e)
+ {
+ super.processFocusEvent(e);
+ }
+
+ /**
+ * Make this method accessible in this Package.
+ */
+ protected final void processHierarchyBoundsEvent(HierarchyEvent e)
+ {
+ super.processHierarchyBoundsEvent(e);
+ }
+
+ /**
+ * Make this method accessible in this Package.
+ */
+ protected final void processHierarchyEvent(HierarchyEvent e)
+ {
+ super.processHierarchyEvent(e);
+ }
+
+ /**
+ * Make this method accessible in this Package.
+ */
+ protected final void processInputMethodEvent(InputMethodEvent e)
+ {
+ super.processInputMethodEvent(e);
+ }
+
+ /**
+ * Make this method accessible in this Package.
+ */
+ protected final void processMouseEvent(MouseEvent e)
+ {
+ super.processMouseEvent(e);
+ }
+
+ /**
+ * Make this method accessible in this Package.
+ */
+ protected final void processMouseWheelEvent(MouseWheelEvent e)
+ {
+ super.processMouseWheelEvent(e);
+ }
+
+ /**
+ * Make this method accessible in this Package.
+ */
+ protected final void processKeyEvent(KeyEvent e)
+ {
+ super.processKeyEvent(e);
+ }
+
+ public void requestFocus() {
+ SwingTextAreaPeer.this.requestFocus(awtComponent, false, true, 0);
+ }
+
+ public boolean requestFocus(boolean temporary) {
+ return SwingTextAreaPeer.this.requestFocus(awtComponent, temporary,
+ true, 0);
+ }
+ }
+
+ /**
+ * The actual JTextArea.
+ */
+ private SwingTextArea jTextArea;
+
+ public SwingTextAreaPeer(TextArea textArea)
+ {
+ super();
+ jTextArea = new SwingTextArea();
+ SwingScrollPane swingArea = new SwingScrollPane(jTextArea);
+ init(textArea, swingArea);
+
+ JViewport viewport = new JViewport()
+ {
+ public Image createImage(int width, int height)
+ {
+ return awtComponent.createImage(width, height);
+ }
+ };
+
+ viewport.setView(jTextArea);
+ swingArea.setViewport(viewport);
+ // Pull over the text from the text area.
+ setText(textArea.getText());
+
+ // Pull over the number of rows and columns
+ // if non were set use default values
+ int columns = textArea.getColumns();
+ int rows = textArea.getRows();
+
+ if(columns == 0 && rows == 0)
+ {
+ columns = 25;
+ textArea.setColumns(columns);
+ rows = 5;
+ textArea.setRows(rows);
+ }
+
+ jTextArea.setColumns(columns);
+ jTextArea.setRows(rows);
+ }
+
+ public Dimension getMinimumSize(int rows, int cols)
+ {
+ return jTextArea.getMinimumSize();
+ }
+
+ public Dimension getPreferredSize(int rows, int cols)
+ {
+ return jTextArea.getPreferredSize();
+ }
+
+ public void insert(String text, int pos)
+ {
+ jTextArea.insert(text, pos);
+ }
+
+ public void insertText(String text, int pos)
+ {
+ jTextArea.insert(text, pos);
+ }
+
+ public Dimension minimumSize()
+ {
+ return jTextArea.getMinimumSize();
+ }
+
+ public Dimension preferredSize()
+ {
+ return jTextArea.getPreferredSize();
+ }
+
+ public Dimension minimumSize(int rows, int cols)
+ {
+ return jTextArea.getMinimumSize();
+ }
+
+ public Dimension preferredSize(int rows, int cols)
+ {
+ return jTextArea.getPreferredSize();
+ }
+
+ public void replaceRange(String text, int start, int end)
+ {
+ jTextArea.replaceRange(text, start, end);
+ }
+
+ public void replaceText(String text, int start, int end)
+ {
+ jTextArea.replaceRange(text, start, end);
+ }
+
+ public long filterEvents(long filter)
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int getCaretPosition()
+ {
+ return jTextArea.getCaretPosition();
+ }
+
+ public Rectangle getCharacterBounds(int pos)
+ {
+ Rectangle r;
+ try
+ {
+ return jTextArea.modelToView(pos);
+ }
+ catch (BadLocationException ex)
+ {
+ r = null;
+ }
+ return r;
+ }
+
+ public int getIndexAtPoint(int x, int y)
+ {
+ return jTextArea.viewToModel(new Point(x, y));
+ }
+
+ public InputMethodRequests getInputMethodRequests()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getSelectionEnd()
+ {
+ return jTextArea.getSelectionEnd();
+ }
+
+ public int getSelectionStart()
+ {
+ return jTextArea.getSelectionStart();
+ }
+
+ public String getText()
+ {
+ return jTextArea.getText();
+ }
+
+ public void select(int start, int end)
+ {
+ jTextArea.select(start, end);
+ }
+
+ public void setCaretPosition(int pos)
+ {
+ jTextArea.setCaretPosition(pos);
+ }
+
+ public void setEditable(boolean editable)
+ {
+ jTextArea.setEditable(editable);
+ }
+
+ public void setText(String text)
+ {
+ jTextArea.setText(text);
+ }
+
+ public void reshape(int x, int y, int width, int height)
+ {
+ if (swingComponent != null)
+ {
+ swingComponent.getJComponent().setBounds(x, y, width, height);
+ swingComponent.getJComponent().validate();
+ }
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java
new file mode 100644
index 000000000..9750c9bf7
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingTextFieldPeer.java
@@ -0,0 +1,411 @@
+/* SwingTextFieldPeer.java -- A Swing based peer for AWT textfields
+ Copyright (C) 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+package gnu.java.awt.peer.swing;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.TextField;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.im.InputMethodRequests;
+import java.awt.peer.TextFieldPeer;
+
+import javax.swing.JComponent;
+import javax.swing.JTextField;
+
+/**
+ * A TextFieldPeer based on Swing JTextField.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class SwingTextFieldPeer
+ extends SwingComponentPeer
+ implements TextFieldPeer
+{
+
+ /**
+ * A specialized Swing textfield for use in the peer.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+ private class SwingTextField
+ extends JTextField
+ implements SwingComponent
+ {
+
+ TextField textField;
+
+ SwingTextField(TextField textField)
+ {
+ this.textField = textField;
+ }
+
+ /**
+ * Overridden to provide normal behaviour even without a real peer
+ * attached.
+ *
+ * @return the location of the textfield on screen
+ */
+ public Point getLocationOnScreen()
+ {
+ return SwingTextFieldPeer.this.getLocationOnScreen();
+ }
+
+ /**
+ * Overridden so that the isShowing method returns the correct value
+ * for the swing button, even if it has no peer on its own.
+ *
+ * @return <code>true</code> if the button is currently showing,
+ * <code>false</code> otherwise
+ */
+ public boolean isShowing()
+ {
+ boolean retVal = false;
+ if (textField != null)
+ retVal = textField.isShowing();
+ return retVal;
+ }
+
+ /**
+ * Overridden, so that the Swing button can create an Image without its
+ * own peer.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ *
+ * @return an image
+ */
+ public Image createImage(int w, int h)
+ {
+ return SwingTextFieldPeer.this.createImage(w, h);
+ }
+
+ /**
+ * Returns this textfield.
+ *
+ * @return <code>this</code>
+ */
+ public JComponent getJComponent()
+ {
+ return this;
+ }
+
+ /**
+ * Handles mouse events by forwarding it to the swing textfield.
+ *
+ * @param ev the mouse event
+ */
+ public void handleMouseEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseEvent(ev);
+ }
+
+ /**
+ * Handles mouse motion events by forwarding it to the swing textfield.
+ *
+ * @param ev the mouse motion event
+ */
+ public void handleMouseMotionEvent(MouseEvent ev)
+ {
+ ev.setSource(this);
+ processMouseMotionEvent(ev);
+ }
+
+ /**
+ * Handles key events by forwarding it to the swing textfield.
+ *
+ * @param ev the key event
+ */
+ public void handleKeyEvent(KeyEvent ev)
+ {
+ ev.setSource(this);
+ processKeyEvent(ev);
+ }
+
+ /**
+ * Handles focus events by forwarding it to
+ * <code>processFocusEvent()</code>.
+ *
+ * @param ev the Focus event
+ */
+ public void handleFocusEvent(FocusEvent ev)
+ {
+ processFocusEvent(ev);
+ }
+
+
+ public Container getParent()
+ {
+ Container par = null;
+ if (textField != null)
+ par = textField.getParent();
+ return par;
+ }
+
+ public Graphics getGraphics()
+ {
+ return SwingTextFieldPeer.this.getGraphics();
+ }
+
+ public void requestFocus() {
+ SwingTextFieldPeer.this.requestFocus(awtComponent, false, true, 0);
+ }
+
+ public boolean requestFocus(boolean temporary) {
+ return SwingTextFieldPeer.this.requestFocus(awtComponent, temporary,
+ true, 0);
+ }
+
+ }
+
+ /**
+ * Creates a new <code>SwingTextFieldPeer</code> instance for the specified
+ * AWT textfield.
+ *
+ * @param textField the AWT textfield
+ */
+ public SwingTextFieldPeer(TextField textField)
+ {
+ SwingTextField swingTextField = new SwingTextField(textField);
+ swingTextField.setText(textField.getText());
+ init(textField, swingTextField);
+ }
+
+ /**
+ * Returns the minimum size of the textfield.
+ *
+ * @param len not used here
+ *
+ * @return the minimum size of the textfield
+ */
+ public Dimension minimumSize(int len)
+ {
+ return swingComponent.getJComponent().getMinimumSize();
+ }
+
+ /**
+ * Returns the preferred size of the textfield.
+ *
+ * @param len not used here
+ *
+ * @return the preferred size of the textfield
+ */
+ public Dimension preferredSize(int len)
+ {
+ return swingComponent.getJComponent().getPreferredSize();
+ }
+
+ /**
+ * Returns the minimum size of the textfield.
+ *
+ * @param len not used here
+ *
+ * @return the minimum size of the textfield
+ */
+ public Dimension getMinimumSize(int len)
+ {
+ return swingComponent.getJComponent().getMinimumSize();
+ }
+
+ /**
+ * Returns the preferred size of the textfield.
+ *
+ * @param len not used here
+ *
+ * @return the preferred size of the textfield
+ */
+ public Dimension getPreferredSize(int len)
+ {
+ return swingComponent.getJComponent().getPreferredSize();
+ }
+
+ /**
+ * Sets the echo character.
+ *
+ * @param echoChar the echo character to be set
+ */
+ public void setEchoChar(char echoChar)
+ {
+ // TODO: Must be implemented.
+ }
+
+ /**
+ * Sets the echo character.
+ *
+ * @param echoChar the echo character to be set
+ */
+ public void setEchoCharacter(char echoChar)
+ {
+ // TODO: Must be implemented.
+ }
+
+ /**
+ * Returns the end index of the current selection.
+ *
+ * @return the end index of the current selection
+ */
+ public int getSelectionEnd()
+ {
+ // TODO: Must be implemented.
+ return 0;
+ }
+
+ /**
+ * Returns the start index of the current selection.
+ *
+ * @return the start index of the current selection
+ */
+ public int getSelectionStart()
+ {
+ // TODO: Must be implemented.
+ return 0;
+ }
+
+ /**
+ * Returns the current content of the textfield.
+ *
+ * @return the current content of the textfield
+ */
+ public String getText()
+ {
+ return ((JTextField) swingComponent.getJComponent()).getText();
+ }
+
+ /**
+ * Sets the content of the textfield.
+ *
+ * @param text the text to set
+ */
+ public void setText(String text)
+ {
+ ((JTextField) swingComponent.getJComponent()).setText(text);
+ }
+
+ /**
+ * Sets the current selection.
+ *
+ * @param startPos the start index of the selection
+ * @param endPos the start index of the selection
+ */
+ public void select(int startPos, int endPos)
+ {
+ // TODO: Must be implemented.
+ }
+
+ /**
+ * Sets the editable flag of the text field.
+ *
+ * @param editable <code>true</code> to make the textfield editable,
+ * <code>false</code> to make it uneditable
+ */
+ public void setEditable(boolean editable)
+ {
+ ((JTextField) swingComponent.getJComponent()).setEditable(editable);
+ }
+
+ /**
+ * Returns the current caret position.
+ *
+ * @return the current caret position
+ */
+ public int getCaretPosition()
+ {
+ return ((JTextField) swingComponent.getJComponent()).getCaret().getDot();
+ }
+
+ /**
+ * Sets the current caret position.
+ *
+ * @param pos the caret position to set
+ */
+ public void setCaretPosition(int pos)
+ {
+ ((JTextField) swingComponent.getJComponent()).getCaret().setDot(pos);
+ }
+
+ /**
+ * Returns the index of the character at the specified location.
+ *
+ * @param x the X coordinate of the point to query
+ * @param y the Y coordinate of the point to query
+ *
+ * @return the index of the character at the specified location
+ */
+ public int getIndexAtPoint(int x, int y)
+ {
+ // TODO: Must be implemented.
+ return 0;
+ }
+
+ /**
+ * Returns the bounds of the character at the specified index.
+ *
+ * @param pos the index of the character
+ *
+ * @return the bounds of the character at the specified index
+ */
+ public Rectangle getCharacterBounds(int pos)
+ {
+ // TODO: Must be implemented.
+ return null;
+ }
+
+ /**
+ * Not used.
+ */
+ public long filterEvents(long filter)
+ {
+ // TODO: Must be implemented.
+ return 0;
+ }
+
+ /**
+ * Not used.
+ */
+ public InputMethodRequests getInputMethodRequests()
+ {
+ // TODO: Must be implemented.
+ return null;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java
new file mode 100644
index 000000000..63414050b
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingToolkit.java
@@ -0,0 +1,181 @@
+/* SwingToolkit.java -- A base toolkit for Swing peers
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Dialog;
+import java.awt.Label;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.TextField;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.TextFieldPeer;
+
+import gnu.java.awt.ClasspathToolkit;
+
+/**
+ * A base implementation for {@link java.awt.Toolkit} that provides the
+ * Swing based widgets. Concrete implementations still must provide the
+ * remaining abstract methods.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public abstract class SwingToolkit extends ClasspathToolkit
+{
+
+ /**
+ * Creates a SwingButtonPeer.
+ *
+ * @param button the AWT button
+ *
+ * @return the Swing button peer
+ */
+ protected ButtonPeer createButton(Button button)
+ {
+ return new SwingButtonPeer(button);
+ }
+
+ /**
+ * Creates a SwingCanvasPeer.
+ *
+ * @param canvas the AWT canvas
+ *
+ * @return the Swing canvas peer
+ */
+ protected CanvasPeer createCanvas(Canvas canvas)
+ {
+ return new SwingCanvasPeer(canvas);
+ }
+
+ /**
+ * Creates a SwingLabelPeer.
+ *
+ * @param label the AWT label
+ *
+ * @return the Swing label peer
+ */
+ protected LabelPeer createLabel(Label label)
+ {
+ return new SwingLabelPeer(label);
+ }
+
+ /**
+ * Creates a SwingMenuPeer.
+ *
+ * @param menu the AWT menu
+ *
+ * @return the Swing menu peer
+ */
+ protected MenuPeer createMenu(Menu menu)
+ {
+ return new SwingMenuPeer(menu);
+ }
+
+ /**
+ * Creates a SwingMenuBarPeer.
+ *
+ * @param menuBar the AWT menubar
+ *
+ * @return the Swing menu bar peer
+ */
+ protected MenuBarPeer createMenuBar(MenuBar menuBar)
+ {
+ return new SwingMenuBarPeer(menuBar);
+ }
+
+ /**
+ * Creates a SwingMenuItemPeer.
+ *
+ * @param menuItem the AWT menu item
+ *
+ * @return the Swing menu item peer
+ */
+ protected MenuItemPeer createMenuItem(MenuItem menuItem)
+ {
+ return new SwingMenuItemPeer(menuItem);
+ }
+
+ /**
+ * Creates a SwingPanelPeer.
+ *
+ * @param panel the AWT panel
+ *
+ * @return the Swing panel peer
+ */
+ protected PanelPeer createPanel(Panel panel)
+ {
+ return new SwingPanelPeer(panel);
+ }
+
+ /**
+ * Creates a SwingTextFieldPeer.
+ *
+ * @param textField the AWT text field
+ *
+ * @return the Swing text field peer
+ */
+ protected TextFieldPeer createTextField(TextField textField)
+ {
+ return new SwingTextFieldPeer(textField);
+ }
+
+ @Override
+ public boolean isModalExclusionTypeSupported
+ (Dialog.ModalExclusionType modalExclusionType)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isModalityTypeSupported(Dialog.ModalityType modalityType)
+ {
+ return false;
+ }
+
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java
new file mode 100644
index 000000000..bdc494e95
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/SwingWindowPeer.java
@@ -0,0 +1,99 @@
+/* SwingWindowPeer.java -- An abstract base for Swing based window peers
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.swing;
+
+import java.awt.Window;
+import java.awt.peer.ComponentPeer;
+import java.awt.peer.WindowPeer;
+
+/**
+ * An abstract base class for Swing based WindowPeer implementation. Concrete
+ * implementations of WindowPeers should subclass this class in order to get
+ * the correct behaviour.
+ *
+ * As a minimum, a subclass must implement all the remaining abstract methods
+ * as well as the following methods:
+ * <ul>
+ * <li>{@link ComponentPeer#getLocationOnScreen()}</li>
+ * <li>{@link ComponentPeer#getGraphics()}</li>
+ * <li>{@link ComponentPeer#createImage(int, int)}</li>
+ * </ul>
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public abstract class SwingWindowPeer
+ extends SwingContainerPeer
+ implements WindowPeer
+{
+
+ /**
+ * Creates a new instance of WindowPeer.
+ *
+ * @param window the AWT window
+ */
+ public SwingWindowPeer(Window window)
+ {
+ super(window);
+ init(window, null);
+ }
+
+ public void updateIconImages()
+ {
+ // TODO: Implement properly.
+ }
+
+ public void updateMinimumSize()
+ {
+ // TODO: Implement properly.
+ }
+
+ public void setModalBlocked(java.awt.Dialog d, boolean b)
+ {
+ // TODO: Implement properly.
+ }
+
+ public void updateFocusableWindowState()
+ {
+ // TODO: Implement properly.
+ }
+
+ public void setAlwaysOnTop(boolean b)
+ {
+ // TODO: Implement properly.
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/swing/package.html b/libjava/classpath/gnu/java/awt/peer/swing/package.html
new file mode 100644
index 000000000..506eda883
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/swing/package.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- package.html - describes classes in gnu.java.awt.peer.swing package.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. -->
+
+<html>
+ <head>
+ <title>Swing based AWT peers</title>
+ </head>
+ <body>
+ <h1>Swing based AWT peers.</h1>
+ <p>This package defines an abstract set of AWT peers that is based on Swing
+ widgets. This can be used as an implementation base for peer implementors
+ who don't have access to native widgets or who want to build a quick
+ prototype of a peer set without implementing all of the AWT widgets.
+ </p>
+ <p>An actual implementation would have to provide the following:
+ <ul>
+ <li>A concrete implementation of {@link java.awt.Toolkit}, possibly based
+ on {@link SwingToolkit}. This implementation must provide all the missing
+ methods of the <code>SwingToolkit</code>.</li>
+ <li>Concrete implementations of {@link java.awt.peer.DialogPeer},
+ {@link java.awt.peer.FramePeer} and {@link java.awt.peer.WindowPeer},
+ ideally based on their <code>SwingXXXPeer</code> counterparts.
+ Some methods must be specially
+ overridden in those peers to provide useful functionality, like
+ <code>getLocationOnScreen()</code>. See the API documentation for more
+ details</li>
+ <li>An implementation of {@link java.awt.Image}. These must be provided by
+ the toplevel component peers.</li>
+ <li>An implementation of {@link java.awt.Graphics}. This must also be
+ provided by the toplevel peers.</li>
+ <li>An implementation of {@link java.awt.Font}. This must be
+ provided by the toolkit.</li>
+ </ul>
+ </p>
+ </body>
+</html>
diff --git a/libjava/classpath/gnu/java/awt/peer/x/GLGraphics.java b/libjava/classpath/gnu/java/awt/peer/x/GLGraphics.java
new file mode 100644
index 000000000..3cf3797ab
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/GLGraphics.java
@@ -0,0 +1,134 @@
+/* GLGraphics.java -- Graphics2D impl on top of GLX
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Color;
+import java.awt.GraphicsConfiguration;
+import java.awt.Rectangle;
+import java.awt.image.ColorModel;
+import java.util.Map;
+
+import gnu.java.awt.java2d.AbstractGraphics2D;
+import gnu.x11.extension.glx.GL;
+
+/**
+ * An implementation of Graphics2D on top of the GLX extension of X.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class GLGraphics extends AbstractGraphics2D
+{
+
+ /**
+ * The rendering context.
+ */
+ private GL gl;
+
+ /**
+ * Creates a new GLGraphics that paints on the specified GL context.
+ *
+ * @param g the GL context to paint to
+ */
+ GLGraphics(GL g)
+ {
+ gl = g;
+ }
+
+ public void setBackground(Color b)
+ {
+ super.setBackground(b);
+
+ gl.clearColor(b.getRed() / 255.F, b.getGreen() / 255.F,
+ b.getBlue() / 255.F, b.getAlpha() / 255.F);
+ }
+
+ public void clearRect(int x, int y, int w, int h)
+ {
+ // TODO: Maybe use fillRect().
+ gl.clear(GL.COLOR_BUFFER_BIT);
+ }
+
+ public void drawLine(int x1, int y1, int x2, int y2)
+ {
+ gl.begin(GL.LINES);
+ gl.vertex2i(x1, y1);
+ gl.vertex2i(x2, y2);
+ gl.end();
+ // TODO: Maybe do:
+ // gl.flush();
+ }
+
+ public void drawRect(int x, int y, int w, int h)
+ {
+ gl.polygon_mode(GL.FRONT_AND_BACK, GL.LINE);
+ gl.begin(GL.POLYGON);
+ gl.recti(x, y, x + w, y + h);
+ gl.end();
+ // TODO: Maybe do:
+ // gl.flush();
+ }
+
+ public void fillRect(int x, int y, int w, int h)
+ {
+ gl.polygon_mode(GL.FRONT_AND_BACK, GL.FILL);
+ gl.recti(x, y, x + w, y + h);
+ // TODO: Maybe do:
+ // gl.flush();
+ }
+
+ protected ColorModel getColorModel()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ @Override
+ protected Rectangle getDeviceBounds()
+ {
+ // FIXME: not sure it's correct
+ return new Rectangle(0, 0,
+ gl.display.default_screen.width,
+ gl.display.default_screen.height);
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/KeyboardMapping.java b/libjava/classpath/gnu/java/awt/peer/x/KeyboardMapping.java
new file mode 100644
index 000000000..c982a30d5
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/KeyboardMapping.java
@@ -0,0 +1,419 @@
+/* KeyboardMapping.java -- Maps X keysyms to Java keyCode and keyChar
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import gnu.x11.Input;
+import gnu.x11.keysym.Latin1;
+import gnu.x11.keysym.Misc;
+
+import java.awt.event.KeyEvent;
+
+/**
+ * Defines the keyboard mapping from X keysyms to Java
+ * keycodes and keychars.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+final class KeyboardMapping
+{
+
+ /**
+ * Maps X keycodes to AWT keycodes.
+ *
+ * @param xInput the X input event
+ * @param xKeyCode the X keycode to map
+ * @param xMods the X modifiers
+ *
+ * @return the AWT keycode and keychar
+ */
+ static int mapToKeyCode(gnu.x11.Input xInput, int xKeyCode, int xMods)
+ {
+ int mapped = KeyEvent.VK_UNDEFINED;
+ int keysym = xInput.keycode_to_keysym(xKeyCode, xMods, true);
+
+ // Special keys.
+ if (keysym >= 255 << 8)
+ {
+ // FIXME: Add missing mappings.
+ switch (keysym)
+ {
+ case Misc.BACKSPACE:
+ mapped = KeyEvent.VK_BACK_SPACE;
+ break;
+ case Misc.TAB:
+ mapped = KeyEvent.VK_TAB;
+ break;
+ case Misc.CLEAR:
+ mapped = KeyEvent.VK_CLEAR;
+ break;
+ case Misc.RETURN:
+ mapped = KeyEvent.VK_ENTER;
+ break;
+ case Misc.PAUSE:
+ mapped = KeyEvent.VK_PAUSE;
+ break;
+ case Misc.SCROLL_LOCK:
+ mapped = KeyEvent.VK_SCROLL_LOCK;
+ break;
+ case Misc.ESCAPE:
+ mapped = KeyEvent.VK_ESCAPE;
+ break;
+ case Misc.HOME:
+ mapped = KeyEvent.VK_HOME;
+ break;
+ case Misc.LEFT:
+ mapped = KeyEvent.VK_LEFT;
+ break;
+ case Misc.UP:
+ mapped = KeyEvent.VK_UP;
+ break;
+ case Misc.RIGHT:
+ mapped = KeyEvent.VK_RIGHT;
+ break;
+ case Misc.DOWN:
+ mapped = KeyEvent.VK_DOWN;
+ break;
+ case Misc.PAGE_UP:
+ mapped = KeyEvent.VK_PAGE_UP;
+ break;
+ case Misc.PAGE_DOWN:
+ mapped = KeyEvent.VK_PAGE_DOWN;
+ break;
+ case Misc.END:
+ mapped = KeyEvent.VK_END;
+ break;
+ case Misc.BEGIN:
+ mapped = KeyEvent.VK_BEGIN;
+ break;
+ case Misc.INSERT:
+ mapped = KeyEvent.VK_INSERT;
+ break;
+ case Misc.UNDO:
+ mapped = KeyEvent.VK_UNDO;
+ break;
+ case Misc.FIND:
+ mapped = KeyEvent.VK_FIND;
+ break;
+ case Misc.CANCEL:
+ mapped = KeyEvent.VK_CANCEL;
+ break;
+ case Misc.HELP:
+ mapped = KeyEvent.VK_HELP;
+ break;
+ case Misc.MODE_SWITCH:
+ mapped = KeyEvent.VK_MODECHANGE;
+ break;
+ case Misc.NUM_LOCK:
+ mapped = KeyEvent.VK_NUM_LOCK;
+ break;
+ case Misc.KP_LEFT:
+ mapped = KeyEvent.VK_KP_LEFT;
+ break;
+ case Misc.KP_UP:
+ mapped = KeyEvent.VK_KP_UP;
+ break;
+ case Misc.KP_RIGHT:
+ mapped = KeyEvent.VK_KP_RIGHT;
+ break;
+ case Misc.KP_DOWN:
+ mapped = KeyEvent.VK_KP_DOWN;
+ break;
+ case Misc.F1:
+ mapped = KeyEvent.VK_F1;
+ break;
+ case Misc.F2:
+ mapped = KeyEvent.VK_F2;
+ break;
+ case Misc.F3:
+ mapped = KeyEvent.VK_F3;
+ break;
+ case Misc.F4:
+ mapped = KeyEvent.VK_F4;
+ break;
+ case Misc.F5:
+ mapped = KeyEvent.VK_F5;
+ break;
+ case Misc.F6:
+ mapped = KeyEvent.VK_F6;
+ break;
+ case Misc.F7:
+ mapped = KeyEvent.VK_F7;
+ break;
+ case Misc.F8:
+ mapped = KeyEvent.VK_F8;
+ break;
+ case Misc.F9:
+ mapped = KeyEvent.VK_F9;
+ break;
+ case Misc.F10:
+ mapped = KeyEvent.VK_F10;
+ break;
+ case Misc.F11:
+ mapped = KeyEvent.VK_F11;
+ break;
+ case Misc.F12:
+ mapped = KeyEvent.VK_F12;
+ break;
+ case Misc.F13:
+ mapped = KeyEvent.VK_F13;
+ break;
+ case Misc.F14:
+ mapped = KeyEvent.VK_F14;
+ break;
+ case Misc.F15:
+ mapped = KeyEvent.VK_F15;
+ break;
+ case Misc.F16:
+ mapped = KeyEvent.VK_F16;
+ break;
+ case Misc.F17:
+ mapped = KeyEvent.VK_F17;
+ break;
+ case Misc.F18:
+ mapped = KeyEvent.VK_F18;
+ break;
+ case Misc.F19:
+ mapped = KeyEvent.VK_F19;
+ break;
+ case Misc.F20:
+ mapped = KeyEvent.VK_F20;
+ break;
+ case Misc.F21:
+ mapped = KeyEvent.VK_F21;
+ break;
+ case Misc.F22:
+ mapped = KeyEvent.VK_F22;
+ break;
+ case Misc.F23:
+ mapped = KeyEvent.VK_F23;
+ break;
+ case Misc.F24:
+ mapped = KeyEvent.VK_F24;
+ break;
+ case Misc.SHIFT_L:
+ case Misc.SHIFT_R:
+ mapped = KeyEvent.VK_SHIFT;
+ break;
+ case Misc.CONTROL_L:
+ case Misc.CONTROL_R:
+ mapped = KeyEvent.VK_CONTROL;
+ break;
+ case Misc.CAPS_LOCK:
+ case Misc.SHIFT_LOCK:
+ mapped = KeyEvent.VK_CAPS_LOCK;
+ break;
+ case Misc.META_L:
+ case Misc.META_R:
+ mapped = KeyEvent.VK_META;
+ break;
+ case Misc.ALT_L:
+ case Misc.ALT_R:
+ mapped = KeyEvent.VK_ALT;
+ break;
+ case Misc.DELETE:
+ mapped = KeyEvent.VK_DELETE;
+ break;
+ default:
+ mapped = KeyEvent.VK_UNDEFINED;
+ }
+ }
+ // Map Latin1 characters.
+ else if (keysym < 256)
+ {
+ // TODO: Add missing mappings, if any.
+ // Lowercase characters are mapped to
+ // their corresponding upper case pendants.
+ if (keysym >= Latin1.A_SMALL && keysym <= Latin1.Z_SMALL)
+ mapped = keysym - 0x20;
+ // Uppercase characters are mapped 1:1.
+ else if (keysym >= Latin1.A && keysym <= Latin1.Z)
+ mapped = keysym;
+ // Digits are mapped 1:1.
+ else if (keysym >= Latin1.NUM_0 && keysym <= Latin1.NUM_9)
+ mapped = keysym;
+ else
+ {
+ switch (keysym)
+ {
+ case Latin1.SPACE:
+ mapped = KeyEvent.VK_SPACE;
+ break;
+ case Latin1.EXCLAM:
+ mapped = KeyEvent.VK_EXCLAMATION_MARK;
+ break;
+ case Latin1.QUOTE_DBL:
+ mapped = KeyEvent.VK_QUOTEDBL;
+ break;
+ case Latin1.NUMBER_SIGN:
+ mapped = KeyEvent.VK_NUMBER_SIGN;
+ break;
+ case Latin1.DOLLAR:
+ mapped = KeyEvent.VK_DOLLAR;
+ break;
+ case Latin1.AMPERSAND:
+ mapped = KeyEvent.VK_AMPERSAND;
+ break;
+ case Latin1.APOSTROPHE:
+ mapped = KeyEvent.VK_QUOTE;
+ break;
+ case Latin1.PAREN_LEFT:
+ mapped = KeyEvent.VK_LEFT_PARENTHESIS;
+ break;
+ case Latin1.PAREN_RIGHT:
+ mapped = KeyEvent.VK_RIGHT_PARENTHESIS;
+ break;
+ case Latin1.ASTERISK:
+ mapped = KeyEvent.VK_ASTERISK;
+ break;
+ case Latin1.PLUS:
+ mapped = KeyEvent.VK_PLUS;
+ break;
+ case Latin1.COMMA:
+ mapped = KeyEvent.VK_COMMA;
+ break;
+ case Latin1.MINUS:
+ mapped = KeyEvent.VK_MINUS;
+ break;
+ case Latin1.PERIOD:
+ mapped = KeyEvent.VK_PERIOD;
+ break;
+ case Latin1.SLASH:
+ mapped = KeyEvent.VK_SLASH;
+ break;
+ case Latin1.COLON:
+ mapped = KeyEvent.VK_COLON;
+ break;
+ case Latin1.SEMICOLON:
+ mapped = KeyEvent.VK_SEMICOLON;
+ break;
+ case Latin1.LESS:
+ mapped = KeyEvent.VK_LESS;
+ break;
+ case Latin1.EQUAL:
+ mapped = KeyEvent.VK_EQUALS;
+ break;
+ case Latin1.GREATER:
+ mapped = KeyEvent.VK_GREATER;
+ break;
+ case Latin1.AT:
+ mapped = KeyEvent.VK_AT;
+ break;
+ case Latin1.BRACKET_LEFT:
+ mapped = KeyEvent.VK_OPEN_BRACKET;
+ break;
+ case Latin1.BACKSLASH:
+ mapped = KeyEvent.VK_BACK_SLASH;
+ break;
+ case Latin1.BRACKET_RIGHT:
+ mapped = KeyEvent.VK_CLOSE_BRACKET;
+ break;
+ case Latin1.ASCII_CIRCUM:
+ mapped = KeyEvent.VK_CIRCUMFLEX;
+ break;
+ case Latin1.UNDERSCORE:
+ mapped = KeyEvent.VK_UNDERSCORE;
+ break;
+ case Latin1.GRAVE:
+ mapped = KeyEvent.VK_DEAD_GRAVE;
+ break;
+ case Latin1.BRACE_LEFT:
+ mapped = KeyEvent.VK_BRACELEFT;
+ break;
+ case Latin1.BRACE_RIGHT:
+ mapped = KeyEvent.VK_BRACERIGHT;
+ break;
+ case Latin1.ASCII_TILDE:
+ mapped = KeyEvent.VK_DEAD_TILDE;
+ break;
+ case Latin1.EXCLAM_DOWN:
+ mapped = KeyEvent.VK_INVERTED_EXCLAMATION_MARK;
+ break;
+ default:
+ mapped = KeyEvent.VK_UNDEFINED;
+ }
+ }
+ }
+ return mapped;
+ }
+
+ /**
+ * Maps X keycodes+modifiers to Java keychars.
+ *
+ * @param xInput The X Input to use for mapping
+ * @param xKeyCode the X keycode
+ * @param xMods the X key modifiers
+ *
+ * @return the Java keychar
+ */
+ static char mapToKeyChar(gnu.x11.Input xInput, int xKeyCode, int xMods)
+ {
+ char mapped = KeyEvent.CHAR_UNDEFINED;
+ char keysym = (char) xInput.keycode_to_keysym(xKeyCode, xMods, false);
+ // FIXME: Map other encodings properly.
+ if (keysym < 256) // Latin1.
+ {
+ mapped = keysym;
+ }
+ return mapped;
+ }
+
+ /**
+ * Maps X modifier masks to AWT modifier masks.
+ *
+ * @param xMods the X modifiers
+ *
+ * @return the AWT modifiers
+ */
+ static int mapModifiers(int xMods)
+ {
+ int mods = 0;
+
+ if ((xMods & Input.SHIFT_MASK) != 0)
+ mods |= KeyEvent.SHIFT_MASK | KeyEvent.SHIFT_DOWN_MASK;
+ if ((xMods & Input.META_MASK) != 0)
+ mods |= KeyEvent.META_MASK | KeyEvent.META_DOWN_MASK;
+ if ((xMods & Input.ALT_MASK) != 0)
+ mods |= KeyEvent.ALT_MASK | KeyEvent.ALT_DOWN_MASK;
+ if ((xMods & Input.MOD5_MASK) != 0)
+ mods |= KeyEvent.ALT_GRAPH_MASK | KeyEvent.ALT_GRAPH_DOWN_MASK;
+ if ((xMods & Input.CONTROL_MASK) != 0)
+ mods |= KeyEvent.CTRL_MASK | KeyEvent.CTRL_DOWN_MASK;
+
+ return mods;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/PixmapVolatileImage.java b/libjava/classpath/gnu/java/awt/peer/x/PixmapVolatileImage.java
new file mode 100644
index 000000000..131647fab
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/PixmapVolatileImage.java
@@ -0,0 +1,185 @@
+/* PixmapVolatileImage.java -- VolatileImage implementation around a Pixmap
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import gnu.x11.GC;
+import gnu.x11.Pixmap;
+import gnu.x11.image.Image;
+import gnu.x11.image.ZPixmap;
+
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.ImageCapabilities;
+import java.awt.Point;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.ComponentSampleModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.ImageObserver;
+import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.VolatileImage;
+import java.awt.image.WritableRaster;
+
+/**
+ * A {@link VolatileImage} implementation that wraps an X Pixmap.
+ */
+class PixmapVolatileImage
+ extends VolatileImage
+{
+
+ /**
+ * The shared capabilities instance.
+ */
+ private static final ImageCapabilities caps = new ImageCapabilities(true);
+
+ /**
+ * The underlying pixmap.
+ */
+ private Pixmap pixmap;
+
+ /**
+ * Creates a new PixmapVolatileImage.
+ *
+ * @param w the width of the image
+ * @param h the height of the image
+ */
+ public PixmapVolatileImage(int w, int h)
+ {
+ GraphicsEnvironment env =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ XGraphicsDevice dev = (XGraphicsDevice) env.getDefaultScreenDevice();
+ pixmap = new Pixmap(dev.getDisplay(), w, h);
+
+ // Clear pixmap.
+ GC gc = new GC(pixmap);
+ gc.set_foreground(0xffffffff);
+ pixmap.fill_rectangle(gc, 0, 0, w, h);
+
+ }
+
+ @Override
+ public boolean contentsLost()
+ {
+ return false;
+ }
+
+ @Override
+ public Graphics2D createGraphics()
+ {
+ return new XGraphics2D(pixmap);
+ }
+
+ @Override
+ public ImageCapabilities getCapabilities()
+ {
+ return caps;
+ }
+
+ @Override
+ public int getHeight()
+ {
+ return pixmap.height;
+ }
+
+ @Override
+ public BufferedImage getSnapshot()
+ {
+ // TODO: Support non-24-bit resolutions.
+ int w = pixmap.width;
+ int h = pixmap.height;
+ ZPixmap zpixmap = (ZPixmap) pixmap.image(0, 0, w, h, 0xffffffff,
+ Image.Format.ZPIXMAP);
+ DataBuffer buffer = new ZPixmapDataBuffer(zpixmap);
+ SampleModel sm = new ComponentSampleModel(DataBuffer.TYPE_BYTE, w, h, 4,
+ w * 4,
+ new int[]{0, 1, 2, 3 });
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
+ ColorModel cm = new ComponentColorModel(cs, true, false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ WritableRaster raster = Raster.createWritableRaster(sm, buffer,
+ new Point(0, 0));
+ return new BufferedImage(cm, raster, false, null);
+ }
+
+ @Override
+ public int getWidth()
+ {
+ return pixmap.width;
+ }
+
+ @Override
+ public int validate(GraphicsConfiguration gc)
+ {
+ // TODO: Check compatibility with gc.
+ return IMAGE_OK;
+ }
+
+ @Override
+ public int getHeight(ImageObserver observer)
+ {
+ return getHeight();
+ }
+
+ @Override
+ public Object getProperty(String name, ImageObserver observer)
+ {
+ return null;
+ }
+
+ @Override
+ public int getWidth(ImageObserver observer)
+ {
+ return getWidth();
+ }
+
+ /**
+ * Returns the underlying X pixmap. This is used for the graphics code.
+ *
+ * @return the underlying X pixmap
+ */
+ Pixmap getPixmap()
+ {
+ return pixmap;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XDialogPeer.java b/libjava/classpath/gnu/java/awt/peer/x/XDialogPeer.java
new file mode 100644
index 000000000..45ad24d67
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XDialogPeer.java
@@ -0,0 +1,61 @@
+/* XDialogPeer.java -- The peer for AWT dialogs
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Dialog;
+import java.awt.peer.DialogPeer;
+
+public class XDialogPeer
+ extends XWindowPeer
+ implements DialogPeer
+{
+
+ XDialogPeer(Dialog target)
+ {
+ super(target);
+ }
+
+ public void setResizable(boolean resizeable)
+ {
+ }
+
+ public void setTitle(String title)
+ {
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XEventPump.java b/libjava/classpath/gnu/java/awt/peer/x/XEventPump.java
new file mode 100644
index 000000000..8e80b97a3
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XEventPump.java
@@ -0,0 +1,486 @@
+/* XEventPump.java -- Pumps events from X to AWT
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.event.ComponentEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+import java.util.HashMap;
+
+import gnu.java.awt.ComponentReshapeEvent;
+import gnu.x11.Atom;
+import gnu.x11.Display;
+import gnu.x11.event.ButtonPress;
+import gnu.x11.event.ButtonRelease;
+import gnu.x11.event.ClientMessage;
+import gnu.x11.event.ConfigureNotify;
+import gnu.x11.event.DestroyNotify;
+import gnu.x11.event.Event;
+import gnu.x11.event.Expose;
+import gnu.x11.event.Input;
+import gnu.x11.event.KeyPress;
+import gnu.x11.event.KeyRelease;
+import gnu.x11.event.MotionNotify;
+import gnu.x11.event.PropertyNotify;
+import gnu.x11.event.ResizeRequest;
+import gnu.x11.event.UnmapNotify;
+
+/**
+ * Fetches events from X, translates them to AWT events and pumps them up
+ * into the AWT event queue.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class XEventPump
+ implements Runnable
+{
+
+ /**
+ * The X Display from which we fetch and pump up events.
+ */
+ private Display display;
+
+ /**
+ * Maps X Windows to AWT Windows to be able to correctly determine the
+ * event targets.
+ */
+ private HashMap windows;
+
+ /**
+ * Indicates if we are currently inside a drag operation. This is
+ * set to the button ID when a button is pressed and to -1 (indicating
+ * that no drag is active) when the mouse is released.
+ */
+ private int drag;
+
+ /**
+ * Creates a new XEventPump for the specified X Display.
+ *
+ * @param d the X Display
+ */
+ XEventPump(Display d)
+ {
+ display = d;
+ windows = new HashMap();
+ drag = -1;
+ Thread thread = new Thread(this, "X Event Pump");
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ /**
+ * The main event pump loop. This basically fetches events from the
+ * X Display and pumps them into the system event queue.
+ */
+ public void run()
+ {
+ while (display.connected)
+ {
+ try
+ {
+ Event xEvent = display.next_event();
+ handleEvent(xEvent);
+ }
+ catch (ThreadDeath death)
+ {
+ // If someone wants to kill us, let them.
+ return;
+ }
+ catch (Throwable x)
+ {
+ System.err.println("Exception during event dispatch:");
+ x.printStackTrace(System.err);
+ }
+ }
+ }
+
+ /**
+ * Adds an X Window to AWT Window mapping. This is required so that the
+ * event pump can correctly determine the event targets.
+ *
+ * @param xWindow the X Window
+ * @param awtWindow the AWT Window
+ */
+ void registerWindow(gnu.x11.Window xWindow, Window awtWindow)
+ {
+ if (XToolkit.DEBUG)
+ System.err.println("registering window id: " + xWindow.id);
+ windows.put(new Integer(xWindow.id), awtWindow);
+ }
+
+ void unregisterWindow(gnu.x11.Window xWindow)
+ {
+ windows.remove(new Integer(xWindow.id));
+ }
+
+ private void handleButtonPress(ButtonPress event)
+ {
+ Integer key = new Integer(event.getEventWindowID());
+ Window awtWindow = (Window) windows.get(key);
+
+ // Create and post the mouse event.
+ int button = event.detail();
+
+ // AWT cannot handle more than 3 buttons and expects 0 instead.
+ if (button >= gnu.x11.Input.BUTTON3)
+ button = 0;
+ drag = button;
+
+ Component target =
+ findMouseEventTarget(awtWindow, event.getEventX(), event.getEventY());
+ if(target == null)
+ {
+ target = awtWindow;
+ }
+
+ MouseEvent mp = new MouseEvent(target, MouseEvent.MOUSE_PRESSED,
+ System.currentTimeMillis(),
+ KeyboardMapping.mapModifiers(event.getState())
+ | buttonToModifier(button),
+ event.getEventX(), event.getEventY(),
+ 1, false, button);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mp);
+ }
+
+ private void handleButtonRelease(ButtonRelease event)
+ {
+ Integer key = new Integer(event.getEventWindowID());
+ Window awtWindow = (Window) windows.get(key);
+
+ int button = event.detail();
+
+ // AWT cannot handle more than 3 buttons and expects 0 instead.
+ if (button >= gnu.x11.Input.BUTTON3)
+ button = 0;
+ drag = -1;
+
+ Component target =
+ findMouseEventTarget(awtWindow, event.getEventX(), event.getEventY());
+ if(target == null)
+ {
+ target = awtWindow;
+ }
+
+ MouseEvent mr = new MouseEvent(target, MouseEvent.MOUSE_RELEASED,
+ System.currentTimeMillis(),
+ KeyboardMapping.mapModifiers(event.getState())
+ | buttonToModifier(button),
+ event.getEventX(), event.getEventY(),
+ 1, false, button);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mr);
+ }
+
+
+ private void handleMotionNotify(MotionNotify event)
+ {
+ Integer key = new Integer(event.getEventWindowID());
+ Window awtWindow = (Window) windows.get(key);
+
+ int button = event.detail();
+
+ // AWT cannot handle more than 3 buttons and expects 0 instead.
+ if (button >= gnu.x11.Input.BUTTON3)
+ button = 0;
+
+ MouseEvent mm = null;
+ if (drag == -1)
+ {
+ mm = new MouseEvent(awtWindow, MouseEvent.MOUSE_MOVED,
+ System.currentTimeMillis(),
+ KeyboardMapping.mapModifiers(event.getState())
+ | buttonToModifier(button),
+ event.getEventX(), event.getEventY(),
+ 1, false);
+
+ }
+ else
+ {
+ mm = new MouseEvent(awtWindow, MouseEvent.MOUSE_DRAGGED,
+ System.currentTimeMillis(),
+ KeyboardMapping.mapModifiers(event.getState())
+ | buttonToModifier(drag),
+ event.getEventX(), event.getEventY(),
+ 1, false);
+ }
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(mm);
+ }
+
+ // FIME: refactor and make faster, maybe caching the event and handle
+ // and/or check timing (timing is generated for PropertyChange)?
+ private void handleExpose(Expose event)
+ {
+ Integer key = new Integer(event.window_id);
+ Window awtWindow = (Window) windows.get(key);
+
+ if (XToolkit.DEBUG)
+ System.err.println("expose request for window id: " + key);
+
+ Rectangle r = new Rectangle(event.x(), event.y(), event.width(),
+ event.height());
+ // We need to clear the background of the exposed rectangle.
+ assert awtWindow != null : "awtWindow == null for window ID: " + key;
+
+ Graphics g = awtWindow.getGraphics();
+ g.clearRect(r.x, r.y, r.width, r.height);
+ g.dispose();
+
+ XWindowPeer xwindow = (XWindowPeer) awtWindow.getPeer();
+ Insets i = xwindow.insets();
+ if (event.width() != awtWindow.getWidth() - i.left - i.right
+ || event.height() != awtWindow.getHeight() - i.top - i.bottom)
+ {
+ int w = event.width();
+ int h = event.height();
+ int x = xwindow.xwindow.x;
+ int y = xwindow.xwindow.y;
+
+ if (XToolkit.DEBUG)
+ System.err.println("Setting size on AWT window: " + w
+ + ", " + h + ", " + awtWindow.getWidth()
+ + ", " + awtWindow.getHeight());
+
+ // new width and height
+ xwindow.xwindow.width = w;
+ xwindow.xwindow.height = h;
+
+ // reshape the window
+ ComponentReshapeEvent cre =
+ new ComponentReshapeEvent(awtWindow, x, y, w, h);
+ awtWindow.dispatchEvent(cre);
+ }
+
+ ComponentEvent ce =
+ new ComponentEvent(awtWindow, ComponentEvent.COMPONENT_RESIZED);
+ awtWindow.dispatchEvent(ce);
+
+ PaintEvent pev = new PaintEvent(awtWindow, PaintEvent.UPDATE, r);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(pev);
+ }
+
+ private void handleDestroyNotify(DestroyNotify destroyNotify)
+ {
+ if (XToolkit.DEBUG)
+ System.err.println("DestroyNotify event: " + destroyNotify);
+
+ Integer key = new Integer(destroyNotify.event_window_id);
+ Window awtWindow = (Window) windows.get(key);
+
+ AWTEvent event = new WindowEvent(awtWindow, WindowEvent.WINDOW_CLOSED);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
+ }
+
+ private void handleClientMessage(ClientMessage clientMessage)
+ {
+ if (XToolkit.DEBUG)
+ System.err.println("ClientMessage event: " + clientMessage);
+
+ if (clientMessage.delete_window())
+ {
+ if (XToolkit.DEBUG)
+ System.err.println("ClientMessage is a delete_window event");
+
+ Integer key = new Integer(clientMessage.window_id);
+ Window awtWindow = (Window) windows.get(key);
+
+ AWTEvent event = new WindowEvent(awtWindow, WindowEvent.WINDOW_CLOSING);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
+ }
+ }
+
+ private void handleEvent(Event xEvent)
+ {
+ if (XToolkit.DEBUG)
+ System.err.println("fetched event: " + xEvent);
+
+ switch (xEvent.code() & 0x7f)
+ {
+ case ButtonPress.CODE:
+ this.handleButtonPress((ButtonPress) xEvent);
+ break;
+ case ButtonRelease.CODE:
+ this.handleButtonRelease((ButtonRelease) xEvent);
+ break;
+ case MotionNotify.CODE:
+ this.handleMotionNotify((MotionNotify) xEvent);
+ break;
+ case Expose.CODE:
+ this.handleExpose((Expose) xEvent);
+ break;
+ case KeyPress.CODE:
+ case KeyRelease.CODE:
+ Integer key = new Integer(((Input) xEvent).getEventWindowID());
+ Window awtWindow = (Window) windows.get(key);
+ handleKeyEvent(xEvent, awtWindow);
+ break;
+ case DestroyNotify.CODE:
+ this.handleDestroyNotify((DestroyNotify) xEvent);
+ break;
+ case ClientMessage.CODE:
+ this.handleClientMessage((ClientMessage) xEvent);
+ break;
+ case PropertyNotify.CODE:
+ key = new Integer (((PropertyNotify) xEvent).getWindowID());
+ awtWindow = (Window) windows.get(key);
+ AWTEvent event = new WindowEvent(awtWindow, WindowEvent.WINDOW_STATE_CHANGED);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
+ break;
+ default:
+ if (XToolkit.DEBUG)
+ System.err.println("Unhandled X event: " + xEvent);
+ }
+ }
+
+ /**
+ * Handles key events from X.
+ *
+ * @param xEvent the X event
+ * @param awtWindow the AWT window to which the event gets posted
+ */
+ private void handleKeyEvent(Event xEvent, Window awtWindow)
+ {
+ Input keyEvent = (Input) xEvent;
+ int xKeyCode = keyEvent.detail();
+ int xMods = keyEvent.getState();
+ int keyCode = KeyboardMapping.mapToKeyCode(xEvent.display.input, xKeyCode,
+ xMods);
+ char keyChar = KeyboardMapping.mapToKeyChar(xEvent.display.input, xKeyCode,
+ xMods);
+ if (XToolkit.DEBUG)
+ System.err.println("XEventPump.handleKeyEvent: " + xKeyCode + ", "
+ + xMods + ": " + ((int) keyChar) + ", " + keyCode);
+ int awtMods = KeyboardMapping.mapModifiers(xMods);
+ long when = System.currentTimeMillis();
+ KeyEvent ke;
+ if (keyEvent.code() == KeyPress.CODE)
+ {
+ ke = new KeyEvent(awtWindow, KeyEvent.KEY_PRESSED, when,
+ awtMods, keyCode,
+ KeyEvent.CHAR_UNDEFINED);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
+ if (keyChar != KeyEvent.CHAR_UNDEFINED)
+ {
+ ke = new KeyEvent(awtWindow, KeyEvent.KEY_TYPED, when,
+ awtMods, KeyEvent.VK_UNDEFINED,
+ keyChar);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
+ }
+
+ }
+ else
+ {
+ ke = new KeyEvent(awtWindow, KeyEvent.KEY_RELEASED, when,
+ awtMods, keyCode,
+ KeyEvent.CHAR_UNDEFINED);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ke);
+ }
+
+ }
+
+ /** Translates an X button identifier to the AWT's MouseEvent modifier
+ * mask. As the AWT cannot handle more than 3 buttons those return
+ * <code>0</code>.
+ */
+ static int buttonToModifier(int button)
+ {
+ switch (button)
+ {
+ case gnu.x11.Input.BUTTON1:
+ return MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON1_MASK;
+ case gnu.x11.Input.BUTTON2:
+ return MouseEvent.BUTTON2_DOWN_MASK | MouseEvent.BUTTON2_MASK;
+ case gnu.x11.Input.BUTTON3:
+ return MouseEvent.BUTTON3_DOWN_MASK | MouseEvent.BUTTON3_MASK;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Finds the heavyweight mouse event target.
+ *
+ * @param src the original source of the event
+ *
+ * @param pt the event coordinates
+ *
+ * @return the real mouse event target
+ */
+ private Component findMouseEventTarget(Component src, int x, int y)
+ {
+ Component found = null;
+ if (src instanceof Container)
+ {
+ Container cont = (Container) src;
+ int numChildren = cont.getComponentCount();
+ for (int i = 0; i < numChildren && found == null; i++)
+ {
+ Component child = cont.getComponent(i);
+ if (child != null && child.isVisible()
+ && child.contains(x - child.getX(), y - child.getY()))
+ {
+ if (child instanceof Container)
+ {
+ Component deeper = findMouseEventTarget(child,
+ x - child.getX(),
+ y - child.getY());
+ if (deeper != null)
+ found = deeper;
+ }
+ else if (! child.isLightweight())
+ found = child;
+ }
+ }
+ }
+
+ // Consider the source itself.
+ if (found == null && src.contains(x, y) && ! src.isLightweight())
+ found = src;
+
+ return found;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XFontPeer.java b/libjava/classpath/gnu/java/awt/peer/x/XFontPeer.java
new file mode 100644
index 000000000..190209014
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XFontPeer.java
@@ -0,0 +1,770 @@
+/* XFontPeer.java -- The font peer for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.awt.AWTError;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.LineMetrics;
+import java.awt.font.TextAttribute;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.CharacterIterator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+
+import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.x11.Display;
+import gnu.x11.Fontable;
+
+/**
+ * The bridge from AWT to X fonts.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class XFontPeer
+ extends ClasspathFontPeer
+{
+
+ /**
+ * The font mapping as specified in the file fonts.properties.
+ */
+ private static Properties fontProperties;
+ static
+ {
+ fontProperties = new Properties();
+ InputStream in = XFontPeer.class.getResourceAsStream("xfonts.properties");
+ try
+ {
+ fontProperties.load(in);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * The FontMetrics implementation for XFontPeer.
+ */
+ private class XFontMetrics
+ extends FontMetrics
+ {
+ /**
+ * The ascent of the font.
+ */
+ int ascent;
+
+ /**
+ * The descent of the font.
+ */
+ int descent;
+
+ /**
+ * The maximum of the character advances.
+ */
+ private int maxAdvance;
+
+ /**
+ * The internal leading.
+ */
+ int leading;
+
+ /**
+ * Cached string metrics. This caches string metrics locally so that the
+ * server doesn't have to be asked each time.
+ */
+ private HashMap metricsCache;
+
+ /**
+ * The widths of the characters indexed by the characters themselves.
+ */
+ private int[] charWidths;
+
+ /**
+ * Creates a new XFontMetrics for the specified font.
+ *
+ * @param font the font
+ */
+ protected XFontMetrics(Font font)
+ {
+ super(font);
+ metricsCache = new HashMap();
+ Fontable.FontInfo info = getXFont().info();
+ ascent = info.font_ascent();
+ descent = info.font_descent();
+ maxAdvance = info.max_bounds().character_width();
+ leading = 0; // TODO: Not provided by X. Possible not needed.
+
+ if (info.min_byte1() == 0 && info.max_byte1() == 0)
+ readCharWidthsLinear(info);
+ else
+ readCharWidthsNonLinear(info);
+ }
+
+ /**
+ * Reads the character widths when specified in a linear fashion. That is
+ * when the min-byte1 and max-byte2 fields are both zero in the X protocol.
+ *
+ * @param info the font info reply
+ */
+ private void readCharWidthsLinear(Fontable.FontInfo info)
+ {
+ int startIndex = info.min_char_or_byte2();
+ int endIndex = info.max_char_or_byte2();
+ charWidths = new int[endIndex + 1];
+ // All the characters before startIndex are zero width.
+ for (int i = 0; i < startIndex; i++)
+ {
+ charWidths[i] = 0;
+ }
+ // All the other character info is fetched from the font info.
+ int index = startIndex;
+ Fontable.FontInfo.CharInfo[] charInfos = info.char_infos();
+ for (Fontable.FontInfo.CharInfo charInfo : charInfos)
+ {
+ charWidths[index] = charInfo.character_width();
+ index++;
+ }
+ }
+
+ private void readCharWidthsNonLinear(Fontable.FontInfo info)
+ {
+ // TODO: Implement.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ /**
+ * Returns the ascent of the font.
+ *
+ * @return the ascent of the font
+ */
+ public int getAscent()
+ {
+ return ascent;
+ }
+
+ /**
+ * Returns the descent of the font.
+ *
+ * @return the descent of the font
+ */
+ public int getDescent()
+ {
+ return descent;
+ }
+
+ /**
+ * Returns the overall height of the font. This is the distance from
+ * baseline to baseline (usually ascent + descent + leading).
+ *
+ * @return the overall height of the font
+ */
+ public int getHeight()
+ {
+ return ascent + descent;
+ }
+
+ /**
+ * Returns the leading of the font.
+ *
+ * @return the leading of the font
+ */
+ public int getLeading()
+ {
+ return leading;
+ }
+
+ /**
+ * Returns the maximum advance for this font.
+ *
+ * @return the maximum advance for this font
+ */
+ public int getMaxAdvance()
+ {
+ return maxAdvance;
+ }
+
+ /**
+ * Determines the width of the specified character <code>c</code>.
+ *
+ * @param c the character
+ *
+ * @return the width of the character
+ */
+ public int charWidth(char c)
+ {
+ int width;
+ if (c > charWidths.length)
+ width = charWidths['?'];
+ else
+ width = charWidths[c];
+ return width;
+ }
+
+ /**
+ * Determines the overall width of the specified string.
+ *
+ * @param c the char buffer holding the string
+ * @param offset the starting offset of the string in the buffer
+ * @param length the number of characters in the string buffer
+ *
+ * @return the overall width of the specified string
+ */
+ public int charsWidth(char[] c, int offset, int length)
+ {
+ int width = 0;
+ if (c.length > 0 && length > 0)
+ {
+ String s = new String(c, offset, length);
+ width = stringWidth(s);
+ }
+ return width;
+ }
+
+ /**
+ * Determines the overall width of the specified string.
+ *
+ * @param s the string
+ *
+ * @return the overall width of the specified string
+ */
+ public int stringWidth(String s)
+ {
+ int width = 0;
+ if (s.length() > 0)
+ {
+ if (metricsCache.containsKey(s))
+ {
+ width = ((Integer) metricsCache.get(s)).intValue();
+ }
+ else
+ {
+ Fontable.TextExtentInfo extents = getXFont().text_extent(s);
+ /*
+ System.err.println("string: '" + s + "' : ");
+ System.err.println("ascent: " + extents.getAscent());
+ System.err.println("descent: " + extents.getDescent());
+ System.err.println("overall ascent: " + extents.getOverallAscent());
+ System.err.println("overall descent: " + extents.getOverallDescent());
+ System.err.println("overall width: " + extents.getOverallWidth());
+ System.err.println("overall left: " + extents.getOverallLeft());
+ System.err.println("overall right: " + extents.getOverallRight());
+ */
+ width = extents.overall_width(); // + extents.overall_left();
+ //System.err.println("String: " + s + ", width: " + width);
+ metricsCache.put(s, new Integer(width));
+ }
+ }
+ //System.err.print("stringWidth: '" + s + "': ");
+ //System.err.println(width);
+ return width;
+ }
+ }
+
+ /**
+ * The LineMetrics implementation for the XFontPeer.
+ */
+ private class XLineMetrics
+ extends LineMetrics
+ {
+
+ /**
+ * Returns the ascent of the font.
+ *
+ * @return the ascent of the font
+ */
+ public float getAscent()
+ {
+ return fontMetrics.ascent;
+ }
+
+ public int getBaselineIndex()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException();
+ }
+
+ public float[] getBaselineOffsets()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the descent of the font.
+ *
+ * @return the descent of the font
+ */
+ public float getDescent()
+ {
+ return fontMetrics.descent;
+ }
+
+ /**
+ * Returns the overall height of the font. This is the distance from
+ * baseline to baseline (usually ascent + descent + leading).
+ *
+ * @return the overall height of the font
+ */
+ public float getHeight()
+ {
+ return fontMetrics.ascent + fontMetrics.descent;
+ }
+
+ /**
+ * Returns the leading of the font.
+ *
+ * @return the leading of the font
+ */
+ public float getLeading()
+ {
+ return fontMetrics.leading;
+ }
+
+ public int getNumChars()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException();
+ }
+
+ public float getStrikethroughOffset()
+ {
+ return 0.F; // TODO: Provided by X??
+ }
+
+ public float getStrikethroughThickness()
+ {
+ return 1.F; // TODO: Provided by X??
+ }
+
+ public float getUnderlineOffset()
+ {
+ return 0.F; // TODO: Provided by X??
+ }
+
+ public float getUnderlineThickness()
+ {
+ return 1.F; // TODO: Provided by X??
+ }
+
+ }
+
+ /**
+ * The X font.
+ */
+ private gnu.x11.Font xfont;
+
+ private String name;
+
+ private int style;
+
+ private int size;
+
+ /**
+ * The font metrics for this font.
+ */
+ XFontMetrics fontMetrics;
+
+ /**
+ * Creates a new XFontPeer for the specified font name, style and size.
+ *
+ * @param name the font name
+ * @param style the font style (bold / italic / normal)
+ * @param size the size of the font
+ */
+ public XFontPeer(String name, int style, int size)
+ {
+ super(name, style, size);
+ this.name = name;
+ this.style = style;
+ this.size = size;
+ }
+
+ /**
+ * Creates a new XFontPeer for the specified font name and style
+ * attributes.
+ *
+ * @param name the font name
+ * @param atts the font attributes
+ */
+ public XFontPeer(String name, Map atts)
+ {
+ super(name, atts);
+ String family = name;
+ if (family == null || family.equals(""))
+ family = (String) atts.get(TextAttribute.FAMILY);
+ if (family == null)
+ family = "SansSerif";
+
+ int size = 12;
+ Float sizeFl = (Float) atts.get(TextAttribute.SIZE);
+ if (sizeFl != null)
+ size = sizeFl.intValue();
+
+ int style = 0;
+ // Detect italic attribute.
+ Float posture = (Float) atts.get(TextAttribute.POSTURE);
+ if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR))
+ style |= Font.ITALIC;
+
+ // Detect bold attribute.
+ Float weight = (Float) atts.get(TextAttribute.WEIGHT);
+ if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0)
+ style |= Font.BOLD;
+
+ this.name = name;
+ this.style = style;
+ this.size = size;
+ }
+
+ /**
+ * Initializes the font peer with the specified attributes. This method is
+ * called from both constructors.
+ *
+ * @param name the font name
+ * @param style the font style
+ * @param size the font size
+ */
+ private void init(String name, int style, int size)
+ {
+ if (name == null)
+ {
+ name = "SansSerif";
+ }
+ GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice dev = env.getDefaultScreenDevice();
+ if (dev instanceof XGraphicsDevice)
+ {
+ Display display = ((XGraphicsDevice) dev).getDisplay();
+ String fontDescr = encodeFont(name, style, size);
+ if (XToolkit.DEBUG)
+ System.err.println("XLFD font description: " + fontDescr);
+ xfont = new gnu.x11.Font(display, fontDescr);
+ }
+ else
+ {
+ throw new AWTError("Local GraphicsEnvironment is not XWindowGraphicsEnvironment");
+ }
+ }
+
+ public boolean canDisplay(Font font, int c)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int canDisplayUpTo(Font font, CharacterIterator i, int start, int limit)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public String getSubFamilyName(Font font, Locale locale)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public String getPostScriptName(Font font)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int getNumGlyphs(Font font)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int getMissingGlyphCode(Font font)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public byte getBaselineFor(Font font, char c)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public String getGlyphName(Font font, int glyphIndex)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public GlyphVector createGlyphVector(Font font, FontRenderContext frc,
+ CharacterIterator ci)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public GlyphVector createGlyphVector(Font font, FontRenderContext ctx,
+ int[] glyphCodes)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public GlyphVector layoutGlyphVector(Font font, FontRenderContext frc,
+ char[] chars, int start, int limit,
+ int flags)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns the font metrics for the specified font.
+ *
+ * @param font the font for which to fetch the font metrics
+ *
+ * @return the font metrics for the specified font
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ if (font.getPeer() != this)
+ throw new AWTError("The specified font has a different peer than this");
+
+ if (fontMetrics == null)
+ fontMetrics = new XFontMetrics(font);
+ return fontMetrics;
+ }
+
+ /**
+ * Frees the font in the X server.
+ */
+ protected void finalize()
+ {
+ if (xfont != null)
+ xfont.close();
+ }
+
+ public boolean hasUniformLineMetrics(Font font)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns the line metrics for this font and the specified string and
+ * font render context.
+ */
+ public LineMetrics getLineMetrics(Font font, CharacterIterator ci, int begin,
+ int limit, FontRenderContext rc)
+ {
+ return new XLineMetrics();
+ }
+
+ public Rectangle2D getMaxCharBounds(Font font, FontRenderContext rc)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Rectangle2D getStringBounds(Font font, CharacterIterator ci,
+ int begin, int limit, FontRenderContext frc)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Encodes a font name + style + size specification into a X logical font
+ * description (XLFD) as described here:
+ *
+ * http://www.meretrx.com/e93/docs/xlfd.html
+ *
+ * This is implemented to look up the font description in the
+ * fonts.properties of this package.
+ *
+ * @param name the font name
+ * @param atts the text attributes
+ *
+ * @return the encoded font description
+ */
+ static String encodeFont(String name, Map atts)
+ {
+ String family = name;
+ if (family == null || family.equals(""))
+ family = (String) atts.get(TextAttribute.FAMILY);
+ if (family == null)
+ family = "SansSerif";
+
+ int size = 12;
+ Float sizeFl = (Float) atts.get(TextAttribute.SIZE);
+ if (sizeFl != null)
+ size = sizeFl.intValue();
+
+ int style = 0;
+ // Detect italic attribute.
+ Float posture = (Float) atts.get(TextAttribute.POSTURE);
+ if (posture != null && !posture.equals(TextAttribute.POSTURE_REGULAR))
+ style |= Font.ITALIC;
+
+ // Detect bold attribute.
+ Float weight = (Float) atts.get(TextAttribute.WEIGHT);
+ if (weight != null && weight.compareTo(TextAttribute.WEIGHT_REGULAR) > 0)
+ style |= Font.BOLD;
+
+ return encodeFont(family, style, size);
+ }
+
+ /**
+ * Encodes a font name + style + size specification into a X logical font
+ * description (XLFD) as described here:
+ *
+ * http://www.meretrx.com/e93/docs/xlfd.html
+ *
+ * This is implemented to look up the font description in the
+ * fonts.properties of this package.
+ *
+ * @param name the font name
+ * @param style the font style
+ * @param size the font size
+ *
+ * @return the encoded font description
+ */
+ static String encodeFont(String name, int style, int size)
+ {
+ CPStringBuilder key = new CPStringBuilder();
+ key.append(validName(name));
+ key.append('.');
+ switch (style)
+ {
+ case Font.BOLD:
+ key.append("bold");
+ break;
+ case Font.ITALIC:
+ key.append("italic");
+ break;
+ case (Font.BOLD | Font.ITALIC):
+ key.append("bolditalic");
+ break;
+ case Font.PLAIN:
+ default:
+ key.append("plain");
+
+ }
+
+ String protoType = fontProperties.getProperty(key.toString());
+ int s = validSize(size);
+ return protoType.replaceFirst("%d", String.valueOf(s));
+ }
+
+ /**
+ * Checks the specified font name for a valid font name. If the font name
+ * is not known, then this returns 'sansserif' as fallback.
+ *
+ * @param name the font name to check
+ *
+ * @return a valid font name
+ */
+ static String validName(String name)
+ {
+ String retVal;
+ if (name.equalsIgnoreCase("sansserif")
+ || name.equalsIgnoreCase("serif")
+ || name.equalsIgnoreCase("monospaced")
+ || name.equalsIgnoreCase("dialog")
+ || name.equalsIgnoreCase("dialoginput"))
+ {
+ retVal = name.toLowerCase();
+ }
+ else
+ {
+ retVal = "sansserif";
+ }
+ return retVal;
+ }
+
+ /**
+ * Translates an arbitrary point size to a size that is typically available
+ * on an X server. These are the sizes 8, 10, 12, 14, 18 and 24.
+ *
+ * @param size the queried size
+ * @return the real available size
+ */
+ private static final int validSize(int size)
+ {
+ int val;
+ if (size <= 9)
+ val = 8;
+ else if (size <= 11)
+ val = 10;
+ else if (size <= 13)
+ val = 12;
+ else if (size <= 17)
+ val = 14;
+ else if (size <= 23)
+ val = 18;
+ else
+ val = 24;
+ return val;
+ }
+
+ /**
+ * Returns the X Font reference. This lazily loads the font when first
+ * requested.
+ *
+ * @return the X Font reference
+ */
+ gnu.x11.Font getXFont()
+ {
+ if (xfont == null)
+ {
+ init(name, style, size);
+ }
+ return xfont;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XFramePeer.java b/libjava/classpath/gnu/java/awt/peer/x/XFramePeer.java
new file mode 100644
index 000000000..cde67778d
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XFramePeer.java
@@ -0,0 +1,145 @@
+/* XFramePeer.java -- The X FramePeer implementation
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.MenuBar;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+import java.awt.peer.FramePeer;
+
+import gnu.java.awt.peer.swing.SwingFramePeer;
+import gnu.x11.Window;
+import gnu.x11.event.Event;
+
+public class XFramePeer
+ extends XWindowPeer
+ implements FramePeer
+{
+
+ XFramePeer(Frame f)
+ {
+ super(f);
+ setTitle(f.getTitle());
+ }
+
+ public void setIconImage(Image image)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void setMenuBar(MenuBar mb)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void setResizable(boolean resizable)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void setTitle(String title)
+ {
+ xwindow.set_wm_name (title);
+ }
+
+ public int getState()
+ {
+ return 0;
+ }
+
+ public void setState(int state)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void setMaximizedBounds(Rectangle r)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Check if this frame peer supports being restacked.
+ *
+ * @return true if this frame peer can be restacked,
+ * false otherwise
+ * @since 1.5
+ */
+ public boolean isRestackSupported()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Sets the bounds of this frame peer.
+ *
+ * @param x the new x co-ordinate
+ * @param y the new y co-ordinate
+ * @param width the new width
+ * @param height the new height
+ * @since 1.5
+ */
+ public void setBoundsPrivate(int x, int y, int width, int height)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Rectangle getBoundsPrivate()
+ {
+ // TODO: Implement this properly.
+ throw new InternalError("Not yet implemented");
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XGraphics2D.java b/libjava/classpath/gnu/java/awt/peer/x/XGraphics2D.java
new file mode 100644
index 000000000..1fce2dcf7
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XGraphics2D.java
@@ -0,0 +1,508 @@
+/* XGraphics2D.java -- A Java based Graphics2D impl for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.Toolkit;
+import java.awt.Transparency;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.ImageObserver;
+import java.awt.image.Raster;
+import java.awt.peer.FontPeer;
+import java.util.HashMap;
+import java.util.WeakHashMap;
+
+import gnu.java.awt.image.AsyncImage;
+import gnu.java.awt.java2d.AbstractGraphics2D;
+import gnu.java.awt.java2d.ScanlineCoverage;
+import gnu.x11.Colormap;
+import gnu.x11.Drawable;
+import gnu.x11.GC;
+import gnu.x11.image.ZPixmap;
+
+public class XGraphics2D
+ extends AbstractGraphics2D
+{
+
+ /**
+ * When this property is set to true, then images are always rendered as
+ * opaque images, ignoring their translucence. This is intended for
+ * debugging and demonstration purposes.
+ */
+ private static final boolean RENDER_OPAQUE =
+ Boolean.getBoolean("escherpeer.renderopaque");
+
+ /**
+ * The X Drawable to draw on.
+ */
+ private Drawable xdrawable;
+
+ /**
+ * The X graphics context (GC).
+ */
+ private GC xgc;
+
+ /**
+ * Indicates if this graphics has already been disposed.
+ */
+ private boolean disposed;
+
+ /**
+ * The current foreground color, possibly null.
+ */
+ private Color foreground;
+
+ XGraphics2D(Drawable d)
+ {
+ super();
+ xdrawable = d;
+ xgc = new GC(d);
+ init();
+ disposed = false;
+ //setClip(new Rectangle(0, 0, xdrawable.width, xdrawable.height));
+ }
+
+ @Override
+ protected void rawDrawLine(int x0, int y0, int x1, int y1)
+ {
+ xdrawable.segment(xgc, x0, y0, x1, y1);
+ }
+
+ @Override
+ protected void rawDrawRect(int x, int y, int w, int h)
+ {
+ xdrawable.rectangle(xgc, x, y, w, h, false);
+ }
+
+ @Override
+ protected void rawFillRect(int x, int y, int w, int h)
+ {
+ xdrawable.rectangle(xgc, x, y, w, h, true);
+ }
+
+ /**
+ * Returns the color model of this Graphics object.
+ *
+ * @return the color model of this Graphics object
+ */
+ protected ColorModel getColorModel()
+ {
+ return Toolkit.getDefaultToolkit().getColorModel();
+ }
+
+ /**
+ * Returns the color model of the target device.
+ *
+ * @return the color model of the target device
+ */
+ protected ColorModel getDestinationColorModel()
+ {
+ return Toolkit.getDefaultToolkit().getColorModel();
+ }
+
+ /**
+ * Returns the bounds of the target.
+ *
+ * @return the bounds of the target
+ */
+ protected Rectangle getDeviceBounds()
+ {
+ return new Rectangle(0, 0, xdrawable.width, xdrawable.height);
+ }
+
+ public GraphicsConfiguration getDeviceConfiguration()
+ {
+ // FIXME: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void dispose()
+ {
+ if (!disposed)
+ {
+ xgc.free();
+ xdrawable.display.flush();
+ disposed = true;
+ }
+ }
+
+ public Graphics create()
+ {
+ // super.create() returns a copy created by clone(), so it should
+ // be a XGraphics2D.
+ XGraphics2D copy = (XGraphics2D) super.create();
+ copy.xgc = xgc.copy();
+ return copy;
+ }
+
+ public void setClip(Shape c)
+ {
+ super.setClip(c);
+ if (c instanceof Rectangle)
+ {
+ Rectangle r = (Rectangle) c;
+ AffineTransform t = getTransform();
+ int translateX = (int) t.getTranslateX();
+ //System.err.println("translateX: " + translateX);
+ int translateY = (int) t.getTranslateY();
+ //System.err.println("translateY: " + translateY);
+ //System.err.println("clip: " + c);
+ gnu.x11.Rectangle clip = new gnu.x11.Rectangle(r.x, r.y, r.width,
+ r.height);
+ xgc.set_clip_rectangles(translateX, translateY,
+ new gnu.x11.Rectangle[]{clip}, GC.UN_SORTED);
+ }
+ }
+
+ /**
+ * Notifies the backend that the raster has changed in the specified
+ * rectangular area. The raster that is provided in this method is always
+ * the same as the one returned in {@link #getDestinationRaster}.
+ * Backends that reflect changes to this raster directly don't need to do
+ * anything here.
+ *
+ * @param raster the updated raster, identical to the raster returned
+ * by {@link #getDestinationRaster()}
+ * @param x the upper left corner of the updated region, X coordinate
+ * @param y the upper lef corner of the updated region, Y coordinate
+ * @param w the width of the updated region
+ * @param h the height of the updated region
+ */
+ protected void updateRaster(Raster raster, int x, int y, int w, int h)
+ {
+ if (w > 0 && h > 0)
+ {
+ ZPixmap zPixmap = new ZPixmap(xdrawable.display, w, h,
+ xdrawable.display.default_pixmap_format);
+ int[] pixel = null;
+ int x1 = x + w;
+ int y1 = y + h;
+ for (int tx = x; tx < x1; tx++)
+ {
+ for (int ty = y; ty < y1; ty++)
+ {
+ pixel = raster.getPixel(tx, ty, pixel);
+ //System.err.println("tx: " + tx + ", ty: " + ty + ", pixel: " + pixel[0] + ", " + pixel[1] + ", " + pixel[2]);
+// System.err.print("r: " + pixel[0]);
+// System.err.print(", g: " + pixel[1]);
+// System.err.println(", b: " + pixel[2]);
+ zPixmap.set_red(tx - x, ty - y, pixel[0]);
+ zPixmap.set_green(tx - x, ty - y, pixel[1]);
+ zPixmap.set_blue(tx - x, ty - y, pixel[2]);
+ }
+ }
+ xdrawable.put_image(xgc, zPixmap, x, y);
+ }
+ }
+
+ @Override
+ public void renderScanline(int y, ScanlineCoverage c)
+ {
+ if (y >= xdrawable.height)
+ return;
+
+ // TODO: Handle Composite and Paint.
+ ScanlineCoverage.Iterator iter = c.iterate();
+ int coverageAlpha = 0;
+ int maxCoverage = c.getMaxCoverage();
+ while (iter.hasNext())
+ {
+ ScanlineCoverage.Range range = iter.next();
+
+ coverageAlpha = range.getCoverage();
+ int x0 = range.getXPos();
+ int l = range.getLength();
+ if (coverageAlpha == c.getMaxCoverage())
+ {
+ // Simply paint the current color over the existing pixels.
+ xdrawable.fill_rectangle(xgc, x0, y, l, 1);
+ }
+ else if (coverageAlpha > 0)
+ {
+ // Composite the current color with the existing pixels.
+ int x1 = x0 + l;
+ x0 = Math.min(Math.max(0, x0), xdrawable.width - 1);
+ x1 = Math.min(Math.max(0, x1), xdrawable.width - 1);
+ if ((x1 - x0) < 1)
+ continue;
+ l = x1 - x0;
+ gnu.x11.image.ZPixmap existing = (ZPixmap)
+ xdrawable.image(x0, y, l, 1, 0xFFFFFFFF,
+ gnu.x11.image.Image.Format.ZPIXMAP);
+ for (int x = 0; x < l; x++)
+ {
+ Color col = getColor();
+ if (col == null)
+ {
+ col = Color.BLACK;
+ }
+ int red = col.getRed();
+ int green = col.getGreen();
+ int blue = col.getBlue();
+ int redOut = existing.get_red(x, 0);
+ int greenOut = existing.get_green(x, 0);
+ int blueOut = existing.get_blue(x, 0);
+ int outAlpha = maxCoverage - coverageAlpha;
+ redOut = redOut * outAlpha + red * coverageAlpha;
+ redOut = redOut / maxCoverage;
+ greenOut = greenOut * outAlpha + green * coverageAlpha;
+ greenOut = greenOut / maxCoverage;
+ blueOut = blueOut * outAlpha + blue * coverageAlpha;
+ blueOut = blueOut / maxCoverage;
+ existing.set(x, 0, redOut, greenOut, blueOut);
+ }
+ xdrawable.put_image(xgc, existing, x0, y);
+ }
+ }
+ }
+
+ protected void init()
+ {
+ super.init();
+ }
+
+ public void setPaint(Paint p)
+ {
+ super.setPaint(p);
+ if (p instanceof Color)
+ {
+ // TODO: Optimize for different standard bit-depths.
+ Color c = (Color) p;
+ /* XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit();
+ HashMap colorMap = tk.colorMap;
+ gnu.x11.Color col = (gnu.x11.Color) colorMap.get(c);
+ if (col == null)
+ {
+ Colormap map = xdrawable.display.default_colormap;
+ col = map.alloc_color (c.getRed() * 256,
+ c.getGreen() * 256,
+ c.getBlue() * 256);
+ colorMap.put(c, col);
+ }*/
+ //xgc.set_foreground(col);
+
+ xgc.set_foreground(c.getRGB());
+ foreground = c;
+ }
+ }
+
+ protected void fillShape(Shape s, boolean isFont)
+ {
+ synchronized (xdrawable.display) {
+ super.fillShape(s, isFont);
+ }
+ }
+
+ private static WeakHashMap<Image,ZPixmap> imageCache = new WeakHashMap<Image,ZPixmap>();
+
+ protected boolean rawDrawImage(Image image, int x, int y, ImageObserver obs)
+ {
+ image = unwrap(image);
+ boolean ret;
+ if (image instanceof XImage)
+ {
+ XImage xImage = (XImage) image;
+ xdrawable.copy_area(xImage.pixmap, xgc, 0, 0, xImage.getWidth(obs),
+ xImage.getHeight(obs), x, y);
+ ret = true;
+ }
+ else if (image instanceof PixmapVolatileImage)
+ {
+ PixmapVolatileImage pvi = (PixmapVolatileImage) image;
+ xdrawable.copy_area(pvi.getPixmap(), xgc, 0, 0, pvi.getWidth(obs),
+ pvi.getHeight(obs), x, y);
+ ret = true;
+ }
+ else if (image instanceof BufferedImage)
+ {
+ BufferedImage bi = (BufferedImage) image;
+ DataBuffer db = bi.getRaster().getDataBuffer();
+ if (db instanceof ZPixmapDataBuffer)
+ {
+ ZPixmapDataBuffer zpmdb = (ZPixmapDataBuffer) db;
+ ZPixmap zpixmap = zpmdb.getZPixmap();
+ xdrawable.put_image(xgc, zpixmap, x, y);
+ ret = true;
+ }
+ else
+ {
+ int transparency = bi.getTransparency();
+ int w = bi.getWidth();
+ int h = bi.getHeight();
+ if (imageCache.containsKey(image))
+ {
+ ZPixmap zpixmap = imageCache.get(image);
+ xdrawable.put_image(xgc, zpixmap, x, y);
+ }
+ else if (transparency == Transparency.OPAQUE || RENDER_OPAQUE)
+ {
+ XGraphicsDevice gd = XToolkit.getDefaultDevice();
+ ZPixmap zpixmap = new ZPixmap(gd.getDisplay(), w, h);
+ for (int yy = 0; yy < h; yy++)
+ {
+ for (int xx = 0; xx < w; xx++)
+ {
+ int rgb = bi.getRGB(xx, yy);
+ zpixmap.set(xx, yy, rgb);
+ }
+ }
+ xdrawable.put_image(xgc, zpixmap, x, y);
+ imageCache.put(image, zpixmap);
+ } else {
+
+ // TODO optimize reusing the rectangles
+ Rectangle source =
+ new Rectangle(0, 0, xdrawable.width, xdrawable.height);
+ Rectangle target = new Rectangle(x, y, w, h);
+
+ Rectangle destination = source.intersection(target);
+
+ x = destination.x;
+ y = destination.y;
+ w = destination.width;
+ h = destination.height;
+
+ ZPixmap zpixmap =
+ (ZPixmap) xdrawable.image(x, y, w, h,
+ 0xffffffff,
+ gnu.x11.image.Image.Format.ZPIXMAP);
+ for (int yy = 0; yy < h; yy++)
+ {
+ for (int xx = 0; xx < w; xx++)
+ {
+ int rgb = bi.getRGB(xx, yy);
+ int alpha = 0xff & (rgb >> 24);
+ if (alpha == 0)
+ {
+ // Completely translucent.
+ rgb = zpixmap.get_red(xx, yy) << 16
+ | zpixmap.get_green(xx, yy) << 8
+ | zpixmap.get_blue(xx, yy);
+ }
+ else if (alpha < 255)
+ {
+ // Composite pixels.
+ int red = 0xff & (rgb >> 16);
+ red = red * alpha
+ + (255 - alpha) * zpixmap.get_red(xx, yy);
+ red = red / 255;
+ int green = 0xff & (rgb >> 8);
+ green = green * alpha
+ + (255 - alpha) * zpixmap.get_green(xx, yy);
+ green = green / 255;
+ int blue = 0xff & rgb;
+ blue = blue * alpha
+ + (255 - alpha) * zpixmap.get_blue(xx, yy);
+ blue = blue / 255;
+ rgb = red << 16 | green << 8 | blue;
+ }
+ // else keep rgb value from source image.
+
+ zpixmap.set(xx, yy, rgb);
+ }
+ }
+ xdrawable.put_image(xgc, zpixmap, x, y);
+ // We can't cache prerendered translucent images, because
+ // we never know how the background changes.
+ }
+ ret = true;
+ }
+ }
+ else
+ {
+ ret = super.rawDrawImage(image, x, y, obs);
+ }
+ return ret;
+ }
+
+ public void setFont(Font f)
+ {
+ super.setFont(f);
+ FontPeer p = getFont().getPeer();
+ if (p instanceof XFontPeer)
+ {
+ XFontPeer xFontPeer = (XFontPeer) p;
+ xgc.set_font(xFontPeer.getXFont());
+ }
+ }
+
+ public void drawString(String s, int x, int y)
+ {
+ FontPeer p = getFont().getPeer();
+ if (p instanceof XFontPeer)
+ {
+ int tx = (int) transform.getTranslateX();
+ int ty = (int) transform.getTranslateY();
+ xdrawable.text(xgc, x + tx, y + ty, s);
+ }
+ else
+ {
+ super.drawString(s, x, y);
+ }
+ }
+
+ /**
+ * Extracts an image instance out of an AsyncImage. If the image isn't
+ * an AsyncImage, then the original instance is returned.
+ *
+ * @param im the image
+ *
+ * @return the image to render
+ */
+ private Image unwrap(Image im)
+ {
+ Image image = im;
+ if (image instanceof AsyncImage)
+ {
+ AsyncImage aIm = (AsyncImage) image;
+ image = aIm.getRealImage();
+ }
+ return image;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XGraphicsConfiguration.java b/libjava/classpath/gnu/java/awt/peer/x/XGraphicsConfiguration.java
new file mode 100644
index 000000000..aed11a3af
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XGraphicsConfiguration.java
@@ -0,0 +1,200 @@
+/* XGraphicsConfiguration.java -- GraphicsConfiguration for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import gnu.x11.Display;
+import gnu.x11.Screen;
+
+import java.awt.Dimension;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.ComponentSampleModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
+import java.awt.image.SampleModel;
+import java.awt.image.VolatileImage;
+import java.awt.image.WritableRaster;
+
+public class XGraphicsConfiguration
+ extends GraphicsConfiguration
+{
+
+ XGraphicsDevice device;
+
+ XGraphicsConfiguration(XGraphicsDevice dev)
+ {
+ device = dev;
+ }
+
+ public GraphicsDevice getDevice()
+ {
+ return device;
+ }
+
+ public BufferedImage createCompatibleImage(int w, int h)
+ {
+ return createCompatibleImage(w, h, Transparency.OPAQUE);
+ }
+
+ public BufferedImage createCompatibleImage(int w, int h, int transparency)
+ {
+ BufferedImage bi;
+ switch (transparency)
+ {
+ case Transparency.OPAQUE:
+ DataBuffer buffer = new ZPixmapDataBuffer(w, h);
+ SampleModel sm = new ComponentSampleModel(DataBuffer.TYPE_BYTE, w, h,
+ 4, w * 4,
+ new int[]{0, 1, 2, 3 });
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
+ ColorModel cm = new ComponentColorModel(cs, true, false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ WritableRaster raster = Raster.createWritableRaster(sm, buffer,
+ new Point(0, 0));
+ bi = new BufferedImage(cm, raster, false, null);
+ break;
+ case Transparency.BITMASK:
+ case Transparency.TRANSLUCENT:
+ bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal transparency: "
+ + transparency);
+ }
+ return bi;
+ }
+
+ public VolatileImage createCompatibleVolatileImage(int w, int h)
+ {
+ return createCompatibleVolatileImage(w, h, Transparency.OPAQUE);
+ }
+
+ public VolatileImage createCompatibleVolatileImage(int width, int height,
+ int transparency)
+ {
+ VolatileImage im;
+ switch (transparency)
+ {
+ case Transparency.OPAQUE:
+ im = new PixmapVolatileImage(width, height);
+ break;
+ case Transparency.BITMASK:
+ case Transparency.TRANSLUCENT:
+ throw new UnsupportedOperationException("Not yet implemented");
+ default:
+ throw new IllegalArgumentException("Unknown transparency type: "
+ + transparency);
+ }
+ return im;
+ }
+
+ public ColorModel getColorModel()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public ColorModel getColorModel(int transparency)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public AffineTransform getDefaultTransform()
+ {
+ return new AffineTransform();
+ }
+
+ public AffineTransform getNormalizingTransform()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Rectangle getBounds()
+ {
+ Display d = device.getDisplay();
+ Screen screen = d.default_screen;
+
+ return new Rectangle(0, 0, screen.width, screen.height);
+ }
+
+ /**
+ * Determines the size of the primary screen.
+ *
+ * @return the size of the primary screen
+ */
+ Dimension getSize()
+ {
+ // TODO: A GraphicsConfiguration should correspond to a Screen instance.
+ Display d = device.getDisplay();
+ Screen screen = d.default_screen;
+ int w = screen.width;
+ int h = screen.height;
+ return new Dimension(w, h);
+ }
+
+ /**
+ * Determines the resolution of the primary screen in pixel-per-inch.
+ *
+ * @returnthe resolution of the primary screen in pixel-per-inch
+ */
+ int getResolution()
+ {
+ Display d = device.getDisplay();
+ Screen screen = d.default_screen;
+ int w = screen.width * 254;
+ int h = screen.height * 254;
+ int wmm = screen.width_in_mm * 10;
+ int hmm = screen.height_in_mm * 10;
+ int xdpi = w / wmm;
+ int ydpi = h / hmm;
+ int dpi = (xdpi + ydpi) / 2;
+ return dpi;
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XGraphicsDevice.java b/libjava/classpath/gnu/java/awt/peer/x/XGraphicsDevice.java
new file mode 100644
index 000000000..6b65e14ed
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XGraphicsDevice.java
@@ -0,0 +1,200 @@
+/* XGraphicsDevice.java -- GraphicsDevice for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.awt.peer.x;
+
+import gnu.classpath.SystemProperties;
+import gnu.x11.Display;
+import gnu.x11.EscherServerConnectionException;
+
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.lang.reflect.Constructor;
+import java.net.Socket;
+
+/**
+ * This class represents an X Display. The actual connection is established
+ * lazily when it is first needed.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class XGraphicsDevice
+ extends GraphicsDevice
+{
+
+ private XGraphicsConfiguration defaultConfiguration;
+
+ /**
+ * The X display associated with the XGraphicsDevice. This is established
+ * when {@link #getDisplay} is first called.
+ */
+ private Display display;
+
+ /**
+ * The display name from which the display will be initialized.
+ */
+ private Display.Name displayName;
+
+ /**
+ * The event pump for this X Display.
+ */
+ private XEventPump eventPump;
+
+ /**
+ * Creates a new XGraphicsDevice.
+ */
+ XGraphicsDevice(Display.Name dn)
+ {
+ displayName = dn;
+ }
+
+ public int getType()
+ {
+ return TYPE_RASTER_SCREEN;
+ }
+
+ public String getIDstring()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public GraphicsConfiguration[] getConfigurations()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public GraphicsConfiguration getDefaultConfiguration()
+ {
+ if (defaultConfiguration == null)
+ defaultConfiguration = new XGraphicsConfiguration(this);
+ return defaultConfiguration;
+ }
+
+ /**
+ * Returns the X Display associated with this XGraphicsDevice.
+ * This establishes the connection to the X server on the first invocation.
+ *
+ * @return the X Display associated with this XGraphicsDevice
+ */
+ Display getDisplay()
+ {
+ if (display == null)
+ {
+ if (displayName.hostname.equals(""))
+ displayName.hostname = "localhost";
+ if (XToolkit.DEBUG)
+ System.err.println("connecting to : " + displayName);
+ // Try to connect via unix domain sockets when host == localhost.
+ if ((displayName.hostname.equals("localhost")
+ || displayName.hostname.equals(""))
+ && SystemProperties.getProperty("gnu.xawt.no_local_sockets") == null)
+ {
+ Socket socket = createLocalSocket();
+ if (socket != null)
+ {
+ try
+ {
+ display = new Display(socket, "localhost",
+ displayName.display_no,
+ displayName.screen_no);
+ }
+ catch (EscherServerConnectionException e)
+ {
+ throw new RuntimeException(e.getCause());
+ }
+ }
+ }
+
+ // The following happens when we are configured to use plain sockets,
+ // when the connection is probably remote or when we couldn't load
+ // the LocalSocket class stuff.
+ if (display == null)
+ {
+ try
+ {
+ display = new Display(displayName);
+ }
+ catch (EscherServerConnectionException e)
+ {
+ throw new RuntimeException(e.getCause());
+ }
+ }
+
+ eventPump = new XEventPump(display);
+ }
+ return display;
+ }
+
+ XEventPump getEventPump()
+ {
+ return eventPump;
+ }
+
+ /**
+ * Tries to load the LocalSocket class and initiate a connection to the
+ * local X server.
+ */
+ private Socket createLocalSocket()
+ {
+ Socket socket = null;
+ try
+ {
+ // TODO: Is this 100% ok?
+ String sockPath = "/tmp/.X11-unix/X" + displayName.display_no;
+ Class localSocketAddressClass =
+ Class.forName("gnu.java.net.local.LocalSocketAddress");
+ Constructor localSocketAddressConstr =
+ localSocketAddressClass.getConstructor(new Class[]{ String.class });
+ Object addr =
+ localSocketAddressConstr.newInstance(new Object[]{ sockPath });
+ Class localSocketClass =
+ Class.forName("gnu.java.net.local.LocalSocket");
+ Constructor localSocketConstructor =
+ localSocketClass.getConstructor(new Class[]{localSocketAddressClass});
+ Object localSocket =
+ localSocketConstructor.newInstance(new Object[]{ addr });
+ socket = (Socket) localSocket;
+ }
+ catch (Exception ex)
+ {
+ // Whatever goes wrong here, we return null.
+ }
+ return socket;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XGraphicsEnvironment.java b/libjava/classpath/gnu/java/awt/peer/x/XGraphicsEnvironment.java
new file mode 100644
index 000000000..7b1d82fee
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XGraphicsEnvironment.java
@@ -0,0 +1,203 @@
+/* XGraphicsEnvironment.java -- Represents the X environment
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import gnu.java.awt.font.OpenTypeFontPeer;
+import gnu.java.awt.java2d.RasterGraphics;
+import gnu.x11.Display;
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.Properties;
+
+/**
+ * Represents the X environment for AWT.
+ *
+ * @author Roman Kennke (kennke@aicas.com)
+ */
+public class XGraphicsEnvironment
+ extends GraphicsEnvironment
+{
+
+ /**
+ * The default graphics device. This is normally the local main X
+ * Display, but can be configured to be any X connection.
+ */
+ private XGraphicsDevice defaultDevice;
+
+ /**
+ * All configured devices.
+ */
+ private XGraphicsDevice[] devices;
+
+ /**
+ * Creates a new XGraphicsEnvironment. This loads the configuration if
+ * there is one present and initializes the XGraphicsDevices in the
+ * environment. If there is no configuration, then there is one
+ * default device initialized with the local main X device.
+ */
+ public XGraphicsEnvironment()
+ {
+ // Initiliaze the devices.
+ Properties props = new Properties();
+ File config = new File(System.getProperty("user.home"),
+ ".xawt.properties");
+
+ try
+ {
+ FileInputStream configIn = new FileInputStream(config);
+ props.load(configIn);
+ int dev = 1;
+ ArrayList deviceList = new ArrayList();
+ while (true)
+ {
+ String propName = "display." + dev;
+ String propValue = props.getProperty(propName);
+ if (propValue != null)
+ {
+ Display.Name displayName = new Display.Name(propValue);
+ XGraphicsDevice device = new XGraphicsDevice(displayName);
+ if (dev == 1)
+ defaultDevice = device;
+ deviceList.add(device);
+ dev++;
+ }
+ else
+ {
+ if (dev == 1)
+ {
+ defaultDevice = initDefaultDevice();
+ deviceList.add(defaultDevice);
+ }
+ break;
+ }
+ }
+ devices = (XGraphicsDevice[]) deviceList.toArray
+ (new XGraphicsDevice[deviceList.size()]);
+ }
+ catch (FileNotFoundException ex)
+ {
+ defaultDevice = initDefaultDevice();
+ devices = new XGraphicsDevice[]{ defaultDevice };
+ }
+ catch (IOException ex)
+ {
+ defaultDevice = initDefaultDevice();
+ devices = new XGraphicsDevice[]{ defaultDevice };
+ }
+
+ }
+
+ /**
+ * Helper method that initializes the default device in the case when there
+ * is no configuration for the default.
+ */
+ private XGraphicsDevice initDefaultDevice()
+ {
+ String display = System.getenv("DISPLAY");
+ if (display == null)
+ display = ":0.0";
+ Display.Name displayName = new Display.Name(display);
+ return new XGraphicsDevice(displayName);
+ }
+
+ /**
+ * Returns all configured screen devices.
+ *
+ * @return all configured screen devices
+ */
+ public GraphicsDevice[] getScreenDevices()
+ {
+ // We return a copy so that nobody can fiddle with our devices.
+ XGraphicsDevice[] copy = new XGraphicsDevice[devices.length];
+ System.arraycopy(devices, 0, copy, 0, devices.length);
+ return copy;
+ }
+
+ /**
+ * Returns the default screen device.
+ *
+ * @return the default screen device
+ */
+ public GraphicsDevice getDefaultScreenDevice()
+ {
+ return defaultDevice;
+ }
+
+ /**
+ * Returns a Graphics instance suitable for drawing on top of the
+ * BufferedImage.
+ *
+ * @param image the buffered image to create a graphics for
+ *
+ * @return a Graphics2D instance for drawing on the BufferedImage
+ */
+ public Graphics2D createGraphics(BufferedImage image)
+ {
+ return new RasterGraphics(image.getRaster(), image.getColorModel());
+ }
+
+ public Font[] getAllFonts()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public String[] getAvailableFontFamilyNames()
+ {
+ return getAvailableFontFamilyNames(Locale.getDefault());
+ }
+
+ public String[] getAvailableFontFamilyNames(Locale l)
+ {
+ // TODO: This doesn't work when we are using X fonts.
+ // Fix this.
+ return OpenTypeFontPeer.getAvailableFontFamilyNames(l);
+ }
+
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XImage.java b/libjava/classpath/gnu/java/awt/peer/x/XImage.java
new file mode 100644
index 000000000..f3df89f4d
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XImage.java
@@ -0,0 +1,178 @@
+/* XImage.java -- Image impl for X Pixmaps
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import gnu.x11.Pixmap;
+import gnu.x11.image.ZPixmap;
+
+import java.awt.Graphics;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+
+import java.awt.image.ColorModel;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class XImage
+ extends Image
+{
+
+ Pixmap pixmap;
+
+ private Hashtable properties;
+
+ XImage(int w, int h)
+ {
+ GraphicsEnvironment env =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ XGraphicsDevice dev = (XGraphicsDevice) env.getDefaultScreenDevice();
+ pixmap = new Pixmap(dev.getDisplay(), w, h);
+ }
+
+ public int getWidth(ImageObserver observer)
+ {
+ return pixmap.width;
+ }
+
+ public int getHeight(ImageObserver observer)
+ {
+ return pixmap.height;
+ }
+
+ public ImageProducer getSource()
+ {
+ return new XImageProducer();
+ }
+
+ /**
+ * Creates an XGraphics for drawing on this XImage.
+ *
+ * @return an XGraphics for drawing on this XImage
+ */
+ public Graphics getGraphics()
+ {
+ XGraphics2D g = new XGraphics2D(pixmap);
+ return g;
+ }
+
+ public Object getProperty(String name, ImageObserver observer)
+ {
+ Object val = null;
+ if (properties != null)
+ val = properties.get(val);
+ return val;
+ }
+
+ public void flush()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected void finalize()
+ {
+ pixmap.free();
+ }
+
+ protected class XImageProducer implements ImageProducer
+ {
+ private Vector<ImageConsumer> consumers = new Vector<ImageConsumer>();
+
+ public void addConsumer(ImageConsumer ic)
+ {
+ if (ic != null && !isConsumer(ic))
+ this.consumers.add(ic);
+ }
+
+ public boolean isConsumer(ImageConsumer ic)
+ {
+ return this.consumers.contains(ic);
+ }
+
+ public void removeConsumer(ImageConsumer ic)
+ {
+ if (ic != null)
+ this.consumers.remove(ic);
+ }
+
+ public void requestTopDownLeftRightResend(ImageConsumer ic)
+ {
+ /* just ignore the call */
+ }
+
+ public void startProduction(ImageConsumer ic)
+ {
+ this.addConsumer(ic);
+
+ for (ImageConsumer consumer : this.consumers)
+ {
+ int width = XImage.this.getWidth(null);
+ int height = XImage.this.getHeight(null);
+
+ XGraphics2D graphics = (XGraphics2D) getGraphics();
+ ColorModel model = graphics.getColorModel();
+ graphics.dispose();
+
+ ZPixmap zpixmap = (ZPixmap)
+ XImage.this.pixmap.image(0, 0, width, height,
+ 0xffffffff,
+ gnu.x11.image.Image.Format.ZPIXMAP);
+
+ int size = zpixmap.get_data_length();
+ System.out.println("size: " + size + ", w = " + width + ", h = " + height);
+
+ int [] pixel = new int[size];
+ for (int i = 0; i < size; i++)
+ pixel[i] = zpixmap.get_data_element(i);
+
+ consumer.setHints(ImageConsumer.SINGLEPASS);
+
+ consumer.setDimensions(width, height);
+ consumer.setPixels(0, 0, width, height, model, pixel, 0, width);
+ consumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
+ }
+
+ System.out.println("done!");
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XToolkit.java b/libjava/classpath/gnu/java/awt/peer/x/XToolkit.java
new file mode 100644
index 000000000..a3eeb0f53
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XToolkit.java
@@ -0,0 +1,667 @@
+/* XToolkit.java -- The central AWT Toolkit for the X peers
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import java.awt.AWTException;
+import java.awt.Button;
+import java.awt.Canvas;
+import java.awt.Checkbox;
+import java.awt.CheckboxMenuItem;
+import java.awt.Choice;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.FileDialog;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Image;
+import java.awt.Label;
+import java.awt.List;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
+import java.awt.Panel;
+import java.awt.PopupMenu;
+import java.awt.PrintJob;
+import java.awt.ScrollPane;
+import java.awt.Scrollbar;
+import java.awt.TextArea;
+import java.awt.TextField;
+import java.awt.Transparency;
+import java.awt.Window;
+import java.awt.Dialog.ModalExclusionType;
+import java.awt.Dialog.ModalityType;
+import java.awt.datatransfer.Clipboard;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.peer.DragSourceContextPeer;
+import java.awt.im.InputMethodHighlight;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.awt.peer.ButtonPeer;
+import java.awt.peer.CanvasPeer;
+import java.awt.peer.CheckboxMenuItemPeer;
+import java.awt.peer.CheckboxPeer;
+import java.awt.peer.ChoicePeer;
+import java.awt.peer.DialogPeer;
+import java.awt.peer.FileDialogPeer;
+import java.awt.peer.FontPeer;
+import java.awt.peer.FramePeer;
+import java.awt.peer.LabelPeer;
+import java.awt.peer.ListPeer;
+import java.awt.peer.MenuBarPeer;
+import java.awt.peer.MenuItemPeer;
+import java.awt.peer.MenuPeer;
+import java.awt.peer.PanelPeer;
+import java.awt.peer.PopupMenuPeer;
+import java.awt.peer.RobotPeer;
+import java.awt.peer.ScrollPanePeer;
+import java.awt.peer.ScrollbarPeer;
+import java.awt.peer.TextAreaPeer;
+import java.awt.peer.TextFieldPeer;
+import java.awt.peer.WindowPeer;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.WeakHashMap;
+
+import javax.imageio.ImageIO;
+
+import gnu.classpath.SystemProperties;
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.EmbeddedWindow;
+import gnu.java.awt.font.OpenTypeFontPeer;
+import gnu.java.awt.image.ImageConverter;
+import gnu.java.awt.java2d.AbstractGraphics2D;
+import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.peer.EmbeddedWindowPeer;
+import gnu.java.awt.peer.swing.SwingButtonPeer;
+import gnu.java.awt.peer.swing.SwingCanvasPeer;
+import gnu.java.awt.peer.swing.SwingCheckboxPeer;
+import gnu.java.awt.peer.swing.SwingLabelPeer;
+import gnu.java.awt.peer.swing.SwingPanelPeer;
+import gnu.java.awt.peer.swing.SwingTextAreaPeer;
+import gnu.java.awt.peer.swing.SwingTextFieldPeer;
+
+public class XToolkit
+ extends ClasspathToolkit
+{
+
+ /**
+ * Set to true to enable debug output.
+ */
+ static boolean DEBUG = false;
+
+ /**
+ * Maps AWT colors to X colors.
+ */
+ HashMap colorMap = new HashMap();
+
+ /**
+ * The system event queue.
+ */
+ private EventQueue eventQueue;
+
+ /**
+ * The default color model of this toolkit.
+ */
+ private ColorModel colorModel;
+
+ /**
+ * Maps image URLs to Image instances.
+ */
+ private HashMap imageCache = new HashMap();
+
+ /**
+ * The cached fonts.
+ */
+ private WeakHashMap<String,ClasspathFontPeer> fontCache =
+ new WeakHashMap<String,ClasspathFontPeer>();
+
+ public XToolkit()
+ {
+ SystemProperties.setProperty("gnu.javax.swing.noGraphics2D", "true");
+ SystemProperties.setProperty("java.awt.graphicsenv",
+ "gnu.java.awt.peer.x.XGraphicsEnvironment");
+ }
+
+ public GraphicsEnvironment getLocalGraphicsEnvironment()
+ {
+ return new XGraphicsEnvironment();
+ }
+
+ /**
+ * Returns the font peer for a font with the specified name and attributes.
+ *
+ * @param name the font name
+ * @param attrs the font attributes
+ *
+ * @return the font peer for a font with the specified name and attributes
+ */
+ public ClasspathFontPeer getClasspathFontPeer(String name, Map attrs)
+ {
+ ClasspathFontPeer font;
+ if ("true".equals(System.getProperty("escherpeer.usexfonts")))
+ {
+ String canonical = XFontPeer.encodeFont(name, attrs);
+ if (!fontCache.containsKey(canonical))
+ {
+ font = new XFontPeer(name, attrs);
+ fontCache.put(canonical, font);
+ }
+ else
+ {
+ font = fontCache.get(canonical);
+ }
+ }
+ else
+ {
+ String canonical = OpenTypeFontPeer.encodeFont(name, attrs);
+ if (!fontCache.containsKey(canonical))
+ {
+ font = new OpenTypeFontPeer(name, attrs);
+ fontCache.put(canonical, font);
+ }
+ else
+ {
+ font = fontCache.get(canonical);
+ }
+ }
+ return font;
+ }
+
+ public Font createFont(int format, InputStream stream)
+ {
+ return null;
+ }
+
+ public RobotPeer createRobot(GraphicsDevice screen) throws AWTException
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public EmbeddedWindowPeer createEmbeddedWindow(EmbeddedWindow w)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected ButtonPeer createButton(Button target)
+ {
+ checkHeadLess("No ButtonPeer can be created in an headless" +
+ "graphics environment.");
+
+ return new SwingButtonPeer(target);
+ }
+
+ protected TextFieldPeer createTextField(TextField target)
+ {
+ checkHeadLess("No TextFieldPeer can be created in an headless " +
+ "graphics environment.");
+
+ return new SwingTextFieldPeer(target);
+ }
+
+ protected LabelPeer createLabel(Label target)
+ {
+ checkHeadLess("No LabelPeer can be created in an headless graphics " +
+ "environment.");
+ return new SwingLabelPeer(target);
+ }
+
+ protected ListPeer createList(List target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected CheckboxPeer createCheckbox(Checkbox target)
+ {
+ checkHeadLess("No CheckboxPeer can be created in an headless graphics " +
+ "environment.");
+
+ return new SwingCheckboxPeer(target);
+ }
+
+ protected ScrollbarPeer createScrollbar(Scrollbar target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected ScrollPanePeer createScrollPane(ScrollPane target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected TextAreaPeer createTextArea(TextArea target)
+ {
+ checkHeadLess("No TextAreaPeer can be created in an headless graphics " +
+ "environment.");
+
+ return new SwingTextAreaPeer(target);
+ }
+
+ protected ChoicePeer createChoice(Choice target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected FramePeer createFrame(Frame target)
+ {
+ XFramePeer frame = new XFramePeer(target);
+ return frame;
+ }
+
+ protected CanvasPeer createCanvas(Canvas target)
+ {
+ return new SwingCanvasPeer(target);
+ }
+
+ protected PanelPeer createPanel(Panel target)
+ {
+ return new SwingPanelPeer(target);
+ }
+
+ protected WindowPeer createWindow(Window target)
+ {
+ return new XWindowPeer(target);
+ }
+
+ protected DialogPeer createDialog(Dialog target)
+ {
+ return new XDialogPeer(target);
+ }
+
+ protected MenuBarPeer createMenuBar(MenuBar target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected MenuPeer createMenu(Menu target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected PopupMenuPeer createPopupMenu(PopupMenu target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected MenuItemPeer createMenuItem(MenuItem target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected FileDialogPeer createFileDialog(FileDialog target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ protected FontPeer getFontPeer(String name, int style)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Dimension getScreenSize()
+ {
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gd = ge.getDefaultScreenDevice();
+ GraphicsConfiguration gc = gd.getDefaultConfiguration();
+ XGraphicsConfiguration xgc = (XGraphicsConfiguration) gc;
+
+ return xgc.getSize();
+ }
+
+ public int getScreenResolution()
+ {
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gd = ge.getDefaultScreenDevice();
+ GraphicsConfiguration gc = gd.getDefaultConfiguration();
+ XGraphicsConfiguration xgc = (XGraphicsConfiguration) gc;
+
+ return xgc.getResolution();
+ }
+
+ /**
+ * Returns the color model used by this toolkit.
+ *
+ * @return the color model used by this toolkit
+ */
+ public ColorModel getColorModel()
+ {
+ // TODO: I assume 24 bit depth here, we can do this better.
+ if (colorModel == null)
+ colorModel = new DirectColorModel(24, 0xFF0000, 0xFF00, 0xFF);
+ return colorModel;
+ }
+
+ public String[] getFontList()
+ {
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ return ge.getAvailableFontFamilyNames();
+ }
+
+ public FontMetrics getFontMetrics(Font name)
+ {
+ ClasspathFontPeer peer = (ClasspathFontPeer) name.getPeer();
+ return peer.getFontMetrics(name);
+ }
+
+ public void sync()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns an image that has its pixel data loaded from a file with the
+ * specified name. If that file doesn't exist, an empty or error image
+ * is returned instead.
+ *
+ * @param name the filename of the file that contains the pixel data
+ *
+ * @return the image
+ */
+ public Image getImage(String name)
+ {
+ Image image;
+ try
+ {
+ File file = new File(name);
+ image = getImage(file.toURL());
+ }
+ catch (MalformedURLException ex)
+ {
+ // TODO: Replace by a more meaningful error image instead.
+ image = null;
+ }
+ return image;
+ }
+
+ /**
+ * Returns an image that has its pixel data loaded from the specified URL.
+ * If the image cannot be loaded for some reason, an empty or error image
+ * is returned instead.
+ *
+ * @param url the URL to the image data
+ *
+ * @return the image
+ */
+ public Image getImage(URL url)
+ {
+ Image image;
+ if (imageCache.containsKey(url))
+ {
+ image = (Image) imageCache.get(url);
+ }
+ else
+ {
+ image = createImage(url);
+ imageCache.put(url, image);
+ }
+ return image;
+ }
+
+ /**
+ * Returns an image that has its pixel data loaded from a file with the
+ * specified name. If that file doesn't exist, an empty or error image
+ * is returned instead.
+ *
+ * @param filename the filename of the file that contains the pixel data
+ *
+ * @return the image
+ */
+ public Image createImage(String filename)
+ {
+ Image im;
+ try
+ {
+ File file = new File(filename);
+ URL url = file.toURL();
+ im = createImage(url);
+ }
+ catch (MalformedURLException ex)
+ {
+ im = createErrorImage();
+ }
+ return im;
+ }
+
+ /**
+ * Returns an image that has its pixel data loaded from the specified URL.
+ * If the image cannot be loaded for some reason, an empty or error image
+ * is returned instead.
+ *
+ * @param url the URL to the image data
+ *
+ * @return the image
+ */
+ public Image createImage(URL url)
+ {
+ Image image;
+ try
+ {
+ image = createImage(url.openStream());
+ }
+ catch (IOException ex)
+ {
+ image = createErrorImage();
+ }
+ return image;
+ }
+
+ /**
+ * Creates an image that is returned when calls to createImage() yields an
+ * error.
+ *
+ * @return an image that is returned when calls to createImage() yields an
+ * error
+ */
+ private Image createErrorImage()
+ {
+ // TODO: Create better error image.
+ return new XImage(1, 1);
+ }
+
+ public boolean prepareImage(Image image, int width, int height, ImageObserver observer)
+ {
+ Image scaled = AbstractGraphics2D.prepareImage(image, width, height);
+ return checkImage(image, width, height, observer) == ImageObserver.ALLBITS;
+ }
+
+ public int checkImage(Image image, int width, int height, ImageObserver observer)
+ {
+ // Images are loaded synchronously, so we don't bother and return true.
+ return ImageObserver.ALLBITS;
+ }
+
+ public Image createImage(ImageProducer producer)
+ {
+ ImageConverter conv = new ImageConverter();
+ producer.startProduction(conv);
+ Image image = conv.getImage();
+ return image;
+ }
+
+ public Image createImage(byte[] data, int offset, int len)
+ {
+ Image image;
+ try
+ {
+ ByteArrayInputStream i = new ByteArrayInputStream(data, offset, len);
+ image = createImage(i);
+ }
+ catch (IOException ex)
+ {
+ image = createErrorImage();
+ }
+ return image;
+ }
+
+ private Image createImage(InputStream i)
+ throws IOException
+ {
+ Image image;
+ BufferedImage buffered = ImageIO.read(i);
+ // If the bufferedimage is opaque, then we can copy it over to an
+ // X Pixmap for faster drawing.
+ if (buffered != null && buffered.getTransparency() == Transparency.OPAQUE)
+ {
+ ImageProducer source = buffered.getSource();
+ image = createImage(source);
+ }
+ else if (buffered != null)
+ {
+ image = buffered;
+ }
+ else
+ {
+ image = createErrorImage();
+ }
+ return image;
+ }
+
+ public PrintJob getPrintJob(Frame frame, String title, Properties props)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void beep()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Clipboard getSystemClipboard()
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns the eventqueue used by the XLib peers.
+ *
+ * @return the eventqueue used by the XLib peers
+ */
+ protected EventQueue getSystemEventQueueImpl()
+ {
+ if (eventQueue == null)
+ eventQueue = new EventQueue();
+ return eventQueue;
+ }
+
+ public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Map mapInputMethodHighlight(InputMethodHighlight highlight)
+ {
+ // TODO: Implement this.
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Helper method to quickly fetch the default device (X Display).
+ *
+ * @return the default XGraphicsDevice
+ */
+ static XGraphicsDevice getDefaultDevice()
+ {
+ XGraphicsEnvironment env = (XGraphicsEnvironment)
+ XGraphicsEnvironment.getLocalGraphicsEnvironment();
+ return (XGraphicsDevice) env.getDefaultScreenDevice();
+ }
+
+ @Override
+ public boolean isModalExclusionTypeSupported(ModalExclusionType modalExclusionType)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean isModalityTypeSupported(ModalityType modalityType)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ private void checkHeadLess(String message) throws HeadlessException
+ {
+ if(GraphicsEnvironment.isHeadless())
+ {
+ if(message == null)
+ message = "This method cannot be called in headless mode.";
+
+ throw new HeadlessException(message);
+ }
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/XWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/x/XWindowPeer.java
new file mode 100644
index 000000000..541eb74fa
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/XWindowPeer.java
@@ -0,0 +1,303 @@
+/* XWindowPeer.java -- Window peer for X
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer.x;
+
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.EventQueue;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.PaintEvent;
+import java.awt.event.WindowEvent;
+import java.awt.image.VolatileImage;
+
+import gnu.x11.Atom;
+import gnu.x11.Window;
+import gnu.x11.event.Event;
+
+import gnu.java.awt.font.OpenTypeFontPeer;
+import gnu.java.awt.peer.ClasspathFontPeer;
+import gnu.java.awt.peer.swing.SwingWindowPeer;
+
+public class XWindowPeer
+ extends SwingWindowPeer
+{
+
+ private static int standardSelect = Event.BUTTON_PRESS_MASK
+ | Event.BUTTON_RELEASE_MASK
+ | Event.POINTER_MOTION_MASK
+ // | Event.RESIZE_REDIRECT_MASK //
+ | Event.EXPOSURE_MASK
+ | Event.PROPERTY_CHANGE_MASK
+ //| Event.STRUCTURE_NOTIFY_MASK
+ //| Event.SUBSTRUCTURE_NOTIFY_MASK
+ | Event.KEY_PRESS_MASK
+ | Event.KEY_RELEASE_MASK
+ //| Event.VISIBILITY_CHANGE_MASK //
+ ;
+
+ /**
+ * The X window.
+ */
+ protected Window xwindow;
+
+ /**
+ * The frame insets. These get updated in {@link #show()}.
+ */
+ private Insets insets;
+
+ XWindowPeer(java.awt.Window window)
+ {
+ super(window);
+ XGraphicsDevice dev = XToolkit.getDefaultDevice();
+
+ // TODO: Maybe initialize lazily in show().
+ Window.Attributes atts = new Window.Attributes();
+ // FIXME: Howto generate a Window without decorations?
+ int x = Math.max(window.getX(), 0);
+ int y = Math.max(window.getY(), 0);
+ int w = Math.max(window.getWidth(), 1);
+ int h = Math.max(window.getHeight(), 1);
+ xwindow = new Window(dev.getDisplay().default_root, x, y, w, h, 0, atts);
+ xwindow.select_input(standardSelect);
+
+ dev.getEventPump().registerWindow(xwindow, window);
+ xwindow.set_wm_delete_window();
+
+ boolean undecorated;
+ if (awtComponent instanceof Frame)
+ {
+ Frame f = (Frame) awtComponent;
+ undecorated = f.isUndecorated();
+ }
+ else if (awtComponent instanceof Dialog)
+ {
+ Dialog d = (Dialog) awtComponent;
+ undecorated = d.isUndecorated();
+ }
+ else
+ {
+ undecorated = true;
+ }
+ if (undecorated)
+ {
+ // First try the Motif implementation of undecorated frames. This
+ // is semantically closest and supported by all major window
+ // managers.
+ // TODO: At the time of writing this, there's no freedesktop.org
+ // standard extension that matches the required semantic. Maybe
+ // undecorated frames are added in the future, if so, then use these.
+ Atom at = Atom.intern(dev.getDisplay(), "_MOTIF_WM_HINTS");
+ if (at != null)
+ {
+ xwindow.change_property(Window.REPLACE, at, at, 32,
+ new int[]{1 << 1, 0, 0, 0, 0}, 0, 5);
+ }
+ }
+ insets = new Insets(0, 0, 0, 0);
+ }
+
+ public void toBack()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void toFront()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateAlwaysOnTop()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean requestWindowFocus()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public Point getLocationOnScreen()
+ {
+ return new Point(xwindow.x, xwindow.y);
+ }
+
+ /**
+ * Returns a XGraphics suitable for drawing on this frame.
+ *
+ * @return a XGraphics suitable for drawing on this frame
+ */
+ public Graphics getGraphics()
+ {
+ XGraphics2D xg2d = new XGraphics2D(xwindow);
+ xg2d.setColor(awtComponent.getForeground());
+ xg2d.setBackground(awtComponent.getBackground());
+ xg2d.setFont(awtComponent.getFont());
+ return xg2d;
+ }
+
+ public Image createImage(int w, int h)
+ {
+ // FIXME: Should return a buffered image.
+ return createVolatileImage(w, h);
+ }
+
+ @Override
+ public VolatileImage createVolatileImage(int width, int height)
+ {
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gd = ge.getDefaultScreenDevice();
+ GraphicsConfiguration gc = gd.getDefaultConfiguration();
+ return gc.createCompatibleVolatileImage(width, height);
+ }
+
+ /**
+ * Makes the component visible. This is called by {@link Component#show()}.
+ *
+ * This is implemented to call setVisible(true) on the Swing component.
+ */
+ public void show()
+ {
+ // Prevent ResizeRedirect events.
+ //xwindow.select_input(Event.NO_EVENT_MASK);
+ //xwindow.select_input(noResizeRedirectSelect);
+
+ XGraphicsDevice dev = XToolkit.getDefaultDevice();
+ xwindow.map();
+ EventQueue eq = XToolkit.getDefaultToolkit().getSystemEventQueue();
+ java.awt.Window w = (java.awt.Window) super.awtComponent;
+ eq.postEvent(new WindowEvent(w, WindowEvent.WINDOW_OPENED));
+ eq.postEvent(new PaintEvent(w, PaintEvent.PAINT,
+ new Rectangle(0, 0, w.getWidth(),
+ w.getHeight())));
+
+ Graphics g = getGraphics();
+ g.clearRect(0, 0, awtComponent.getWidth(), awtComponent.getHeight());
+ g.dispose();
+// // Reset input selection.
+// atts.set_override_redirect(false);
+// xwindow.change_attributes(atts);
+
+ // Determine the frame insets.
+ Atom atom = (Atom) Atom.intern(dev.getDisplay(), "_NET_FRAME_EXTENTS");
+ Window.Property p = xwindow.get_property(false, atom, Atom.CARDINAL, 0,
+ Window.MAX_WM_LENGTH);
+ if (p.format() != 0)
+ {
+ insets = new Insets(p.value(0), p.value(1), p.value(2), p.value(3));
+ Window.Changes ch = new Window.Changes();
+ ch.width(awtComponent.getWidth() - insets.left - insets.top);
+ ch.height(awtComponent.getHeight() - insets.top - insets.bottom);
+ xwindow.configure(ch);
+ }
+
+ }
+
+ /**
+ * Makes the component invisible. This is called from
+ * {@link Component#hide()}.
+ *
+ * This is implemented to call setVisible(false) on the Swing component.
+ */
+ public void hide()
+ {
+ xwindow.unmap();
+ }
+
+ /**
+ * Notifies the peer that the bounds of this component have changed. This
+ * is called by {@link Component#reshape(int, int, int, int)}.
+ *
+ * This is implemented to call setBounds() on the Swing component.
+ *
+ * @param x the X coordinate of the upper left corner of the component
+ * @param y the Y coordinate of the upper left corner of the component
+ * @param width the width of the component
+ * @param height the height of the component
+ */
+ public void reshape(int x, int y, int width, int height)
+ {
+ Insets i = insets;
+ xwindow.move_resize(x - i.left, y - i.right, width - i.left - i.right,
+ height - i.top - i.bottom);
+ }
+
+ public Insets insets()
+ {
+ return (Insets) insets.clone();
+ }
+
+ /**
+ * Returns the font metrics for the specified font.
+ *
+ * @return the font metrics for the specified font
+ */
+ public FontMetrics getFontMetrics(Font font)
+ {
+ ClasspathFontPeer fontPeer = (ClasspathFontPeer) font.getPeer();
+ return fontPeer.getFontMetrics(font);
+ }
+
+ /**
+ * Unregisters the window in the event pump when it is closed.
+ */
+ protected void finalize()
+ {
+ XGraphicsDevice dev = XToolkit.getDefaultDevice();
+ dev.getEventPump().unregisterWindow(xwindow);
+ }
+
+ public Window getXwindow()
+ {
+ return xwindow;
+ }
+}
diff --git a/libjava/classpath/gnu/java/awt/peer/x/ZPixmapDataBuffer.java b/libjava/classpath/gnu/java/awt/peer/x/ZPixmapDataBuffer.java
new file mode 100644
index 000000000..cf40f4d69
--- /dev/null
+++ b/libjava/classpath/gnu/java/awt/peer/x/ZPixmapDataBuffer.java
@@ -0,0 +1,67 @@
+package gnu.java.awt.peer.x;
+
+import gnu.x11.Display;
+import gnu.x11.image.ZPixmap;
+
+import java.awt.GraphicsEnvironment;
+import java.awt.image.DataBuffer;
+
+/**
+ * A DataBuffer implementation that is based on a ZPixmap. This is used
+ * as backing store for BufferedImages.
+ */
+class ZPixmapDataBuffer
+ extends DataBuffer
+{
+
+ /**
+ * The backing ZPixmap.
+ */
+ private ZPixmap zpixmap;
+
+ /**
+ * Creates a new ZPixmapDataBuffer with a specified width and height.
+ *
+ * @param d the X display
+ * @param w the width
+ * @param h the height
+ */
+ ZPixmapDataBuffer(int w, int h)
+ {
+ super(TYPE_BYTE, w * h * 3); // TODO: Support non-24-bit-resolutions.
+ GraphicsEnvironment env =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ XGraphicsDevice dev = (XGraphicsDevice) env.getDefaultScreenDevice();
+ Display d = dev.getDisplay();
+ zpixmap = new ZPixmap(d, w, h, d.default_pixmap_format);
+ }
+
+ /**
+ * Creates a ZPixmapDataBuffer from an existing ZPixmap.
+ *
+ * @param zpixmap the ZPixmap to wrap
+ */
+ ZPixmapDataBuffer(ZPixmap zpixmap)
+ {
+ super(TYPE_BYTE, zpixmap.get_data_length());
+ this.zpixmap = zpixmap;
+ }
+
+ @Override
+ public int getElem(int bank, int i)
+ {
+ return 0xff & zpixmap.get_data_element(i);
+ }
+
+ @Override
+ public void setElem(int bank, int i, int val)
+ {
+ zpixmap.set_data_element(i, (byte) val);
+ }
+
+ ZPixmap getZPixmap()
+ {
+ return zpixmap;
+ }
+
+}