1 /* GtkToolkit.java -- Implements an AWT Toolkit using GTK for peers
2 Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu
.java
.awt
.peer
.gtk
;
41 import gnu
.classpath
.Configuration
;
42 import gnu
.java
.awt
.EmbeddedWindow
;
43 import gnu
.java
.awt
.peer
.ClasspathFontPeer
;
44 import gnu
.java
.awt
.peer
.ClasspathTextLayoutPeer
;
45 import gnu
.java
.awt
.peer
.EmbeddedWindowPeer
;
48 import java
.awt
.datatransfer
.Clipboard
;
49 import java
.awt
.dnd
.DragGestureEvent
;
50 import java
.awt
.dnd
.peer
.DragSourceContextPeer
;
51 import java
.awt
.font
.FontRenderContext
;
52 import java
.awt
.im
.InputMethodHighlight
;
53 import java
.awt
.image
.BufferedImage
;
54 import java
.awt
.image
.ColorModel
;
55 import java
.awt
.image
.DirectColorModel
;
56 import java
.awt
.image
.ImageConsumer
;
57 import java
.awt
.image
.ImageObserver
;
58 import java
.awt
.image
.ImageProducer
;
59 import java
.awt
.peer
.*;
60 import java
.io
.InputStream
;
62 import java
.text
.AttributedString
;
63 import java
.util
.HashMap
;
64 import java
.util
.HashSet
;
65 import java
.util
.Hashtable
;
66 import java
.util
.Iterator
;
67 import java
.util
.LinkedHashMap
;
69 import java
.util
.Properties
;
71 import javax
.imageio
.spi
.IIORegistry
;
73 /* This class uses a deprecated method java.awt.peer.ComponentPeer.getPeer().
74 This merits comment. We are basically calling Sun's bluff on this one.
75 We think Sun has deprecated it simply to discourage its use as it is
76 bad programming style. However, we need to get at a component's peer in
77 this class. If getPeer() ever goes away, we can implement a hash table
78 that will keep up with every window's peer, but for now this is faster. */
81 * This class accesses a system property called
82 * <tt>gnu.java.awt.peer.gtk.Graphics</tt>. If the property is defined and
83 * equal to "Graphics2D", the cairo-based GdkGraphics2D will be used in
84 * drawing contexts. Any other value will cause the older GdkGraphics
87 public class GtkToolkit
extends gnu
.java
.awt
.ClasspathToolkit
89 Hashtable containers
= new Hashtable();
91 static boolean useGraphics2dSet
;
92 static boolean useGraphics2d
;
93 static Thread mainThread
;
95 public static boolean useGraphics2D()
99 useGraphics2d
= System
.getProperty("gnu.java.awt.peer.gtk.Graphics",
100 "Graphics").equals("Graphics2D");
101 useGraphics2dSet
= true;
102 return useGraphics2d
;
105 static native void gtkInit(int portableNativeSync
);
109 if (Configuration
.INIT_LOAD_LIBRARY
)
110 System
.loadLibrary("gtkpeer");
112 int portableNativeSync
;
113 String portNatSyncProp
=
114 System
.getProperty("gnu.classpath.awt.gtk.portable.native.sync");
116 if (portNatSyncProp
== null)
117 portableNativeSync
= -1; // unset
118 else if (Boolean
.valueOf(portNatSyncProp
).booleanValue())
119 portableNativeSync
= 1; // true
121 portableNativeSync
= 0; // false
123 gtkInit(portableNativeSync
);
125 mainThread
= new Thread ("GTK main thread")
139 public native void beep();
140 private native void getScreenSizeDimensions(int[] xy
);
142 public int checkImage (Image image
, int width
, int height
,
143 ImageObserver observer
)
145 int status
= ImageObserver
.ALLBITS
146 | ImageObserver
.WIDTH
147 | ImageObserver
.HEIGHT
;
149 if (image
instanceof GtkImage
)
150 return ((GtkImage
) image
).checkImage (observer
);
152 if (observer
!= null)
153 observer
.imageUpdate (image
, status
,
155 image
.getWidth (observer
),
156 image
.getHeight (observer
));
162 * A helper class to return to clients in cases where a BufferedImage is
163 * desired but its construction fails.
165 private class GtkErrorImage
extends Image
167 public GtkErrorImage()
171 public int getWidth(ImageObserver observer
)
176 public int getHeight(ImageObserver observer
)
181 public ImageProducer
getSource()
184 return new ImageProducer()
186 HashSet consumers
= new HashSet();
187 public void addConsumer(ImageConsumer ic
)
192 public boolean isConsumer(ImageConsumer ic
)
194 return consumers
.contains(ic
);
197 public void removeConsumer(ImageConsumer ic
)
199 consumers
.remove(ic
);
202 public void startProduction(ImageConsumer ic
)
205 Iterator i
= consumers
.iterator();
208 ImageConsumer c
= (ImageConsumer
) i
.next();
209 c
.imageComplete(ImageConsumer
.IMAGEERROR
);
212 public void requestTopDownLeftRightResend(ImageConsumer ic
)
219 public Graphics
getGraphics()
224 public Object
getProperty(String name
, ImageObserver observer
)
228 public Image
getScaledInstance(int width
, int height
, int flags
)
230 return new GtkErrorImage();
240 * Helper to return either a BufferedImage -- the argument -- or a
241 * GtkErrorImage if the argument is null.
244 private Image
bufferedImageOrError(BufferedImage b
)
247 return new GtkErrorImage();
253 public Image
createImage (String filename
)
255 if (filename
.length() == 0)
256 return new GtkImage ();
259 return bufferedImageOrError(GdkPixbufDecoder
.createBufferedImage (filename
));
261 return new GtkImage (filename
);
264 public Image
createImage (URL url
)
267 return bufferedImageOrError(GdkPixbufDecoder
.createBufferedImage (url
));
269 return new GtkImage (url
);
272 public Image
createImage (ImageProducer producer
)
275 return bufferedImageOrError(GdkPixbufDecoder
.createBufferedImage (producer
));
277 return new GtkImage (producer
);
280 public Image
createImage (byte[] imagedata
, int imageoffset
,
284 return bufferedImageOrError(GdkPixbufDecoder
.createBufferedImage (imagedata
,
289 byte[] datacopy
= new byte[imagelength
];
290 System
.arraycopy (imagedata
, imageoffset
, datacopy
, 0, imagelength
);
291 return new GtkImage (datacopy
);
296 * Creates an ImageProducer from the specified URL. The image is assumed
297 * to be in a recognised format.
299 * @param url URL to read image data from.
301 public ImageProducer
createImageProducer(URL url
)
303 return new GdkPixbufDecoder(url
);
307 * Returns the native color model (which isn't the same as the default
308 * ARGB color model, but doesn't have to be).
310 public ColorModel
getColorModel ()
312 /* Return the GDK-native ABGR format */
313 return new DirectColorModel(32,
320 public String
[] getFontList ()
322 return (new String
[] { "Dialog",
329 private class LRUCache
extends LinkedHashMap
332 public LRUCache(int max
)
334 super(max
, 0.75f
, true);
337 protected boolean removeEldestEntry(Map
.Entry eldest
)
339 return size() > max_entries
;
343 private LRUCache fontCache
= new LRUCache(50);
344 private LRUCache metricsCache
= new LRUCache(50);
345 private LRUCache imageCache
= new LRUCache(50);
347 public FontMetrics
getFontMetrics (Font font
)
349 synchronized (metricsCache
)
351 if (metricsCache
.containsKey(font
))
352 return (FontMetrics
) metricsCache
.get(font
);
355 FontMetrics m
= new GdkFontMetrics (font
);
356 synchronized (metricsCache
)
358 metricsCache
.put(font
, m
);
363 public Image
getImage (String filename
)
365 if (imageCache
.containsKey(filename
))
366 return (Image
) imageCache
.get(filename
);
369 Image im
= createImage(filename
);
370 imageCache
.put(filename
, im
);
375 public Image
getImage (URL url
)
377 if (imageCache
.containsKey(url
))
378 return (Image
) imageCache
.get(url
);
381 Image im
= createImage(url
);
382 imageCache
.put(url
, im
);
387 public PrintJob
getPrintJob (Frame frame
, String jobtitle
, Properties props
)
392 public native int getScreenResolution();
394 public Dimension
getScreenSize ()
396 int dim
[] = new int[2];
397 getScreenSizeDimensions(dim
);
398 return new Dimension(dim
[0], dim
[1]);
401 public Clipboard
getSystemClipboard()
403 SecurityManager secman
= System
.getSecurityManager();
405 secman
.checkSystemClipboardAccess();
407 return GtkClipboard
.getInstance();
411 * Prepares a GtkImage. For every other kind of Image it just
412 * assumes the image is already prepared for rendering.
414 public boolean prepareImage (Image image
, int width
, int height
,
415 ImageObserver observer
)
417 /* GtkImages are always prepared, as long as they're loaded. */
418 if (image
instanceof GtkImage
)
419 return ((((GtkImage
)image
).checkImage (observer
) &
420 ImageObserver
.ALLBITS
) != 0);
422 /* Assume anything else is too */
426 public native void sync();
428 protected void setComponentState (Component c
, GtkComponentPeer cp
)
430 /* Make the Component reflect Peer defaults */
431 if (c
.getForeground () == null)
432 c
.setForeground (cp
.getForeground ());
433 if (c
.getBackground () == null)
434 c
.setBackground (cp
.getBackground ());
435 // if (c.getFont () == null)
436 // c.setFont (cp.getFont ());
438 /* Make the Peer reflect the state of the Component */
439 if (! (c
instanceof Window
))
441 cp
.setCursor (c
.getCursor ());
443 Rectangle bounds
= c
.getBounds ();
444 cp
.setBounds (bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
);
445 cp
.setVisible (c
.isVisible ());
449 protected ButtonPeer
createButton (Button b
)
451 return new GtkButtonPeer (b
);
454 protected CanvasPeer
createCanvas (Canvas c
)
456 return new GtkCanvasPeer (c
);
459 protected CheckboxPeer
createCheckbox (Checkbox cb
)
461 return new GtkCheckboxPeer (cb
);
464 protected CheckboxMenuItemPeer
createCheckboxMenuItem (CheckboxMenuItem cmi
)
466 return new GtkCheckboxMenuItemPeer (cmi
);
469 protected ChoicePeer
createChoice (Choice c
)
471 return new GtkChoicePeer (c
);
474 protected DialogPeer
createDialog (Dialog d
)
476 return new GtkDialogPeer (d
);
479 protected FileDialogPeer
createFileDialog (FileDialog fd
)
481 return new GtkFileDialogPeer (fd
);
484 protected FramePeer
createFrame (Frame f
)
486 return new GtkFramePeer (f
);
489 protected LabelPeer
createLabel (Label label
)
491 return new GtkLabelPeer (label
);
494 protected ListPeer
createList (List list
)
496 return new GtkListPeer (list
);
499 protected MenuPeer
createMenu (Menu m
)
501 return new GtkMenuPeer (m
);
504 protected MenuBarPeer
createMenuBar (MenuBar mb
)
506 return new GtkMenuBarPeer (mb
);
509 protected MenuItemPeer
createMenuItem (MenuItem mi
)
511 return new GtkMenuItemPeer (mi
);
514 protected PanelPeer
createPanel (Panel p
)
516 return new GtkPanelPeer (p
);
519 protected PopupMenuPeer
createPopupMenu (PopupMenu target
)
521 return new GtkPopupMenuPeer (target
);
524 protected ScrollPanePeer
createScrollPane (ScrollPane sp
)
526 return new GtkScrollPanePeer (sp
);
529 protected ScrollbarPeer
createScrollbar (Scrollbar sb
)
531 return new GtkScrollbarPeer (sb
);
534 protected TextAreaPeer
createTextArea (TextArea ta
)
536 return new GtkTextAreaPeer (ta
);
539 protected TextFieldPeer
createTextField (TextField tf
)
541 return new GtkTextFieldPeer (tf
);
544 protected WindowPeer
createWindow (Window w
)
546 return new GtkWindowPeer (w
);
549 public EmbeddedWindowPeer
createEmbeddedWindow (EmbeddedWindow w
)
551 return new GtkEmbeddedWindowPeer (w
);
555 * @deprecated part of the older "logical font" system in earlier AWT
556 * implementations. Our newer Font class uses getClasspathFontPeer.
558 protected FontPeer
getFontPeer (String name
, int style
) {
559 // All fonts get a default size of 12 if size is not specified.
560 return getFontPeer(name
, style
, 12);
564 * Private method that allows size to be set at initialization time.
566 private FontPeer
getFontPeer (String name
, int style
, int size
)
568 Map attrs
= new HashMap ();
569 ClasspathFontPeer
.copyStyleToAttrs (style
, attrs
);
570 ClasspathFontPeer
.copySizeToAttrs (size
, attrs
);
571 return getClasspathFontPeer (name
, attrs
);
575 * Newer method to produce a peer for a Font object, even though Sun's
576 * design claims Font should now be peerless, we do not agree with this
577 * model, hence "ClasspathFontPeer".
580 public ClasspathFontPeer
getClasspathFontPeer (String name
, Map attrs
)
582 Map keyMap
= new HashMap (attrs
);
583 // We don't know what kind of "name" the user requested (logical, face,
584 // family), and we don't actually *need* to know here. The worst case
585 // involves failure to consolidate fonts with the same backend in our
586 // cache. This is harmless.
587 keyMap
.put ("GtkToolkit.RequestedFontName", name
);
588 if (fontCache
.containsKey (keyMap
))
589 return (ClasspathFontPeer
) fontCache
.get (keyMap
);
592 ClasspathFontPeer newPeer
= new GdkFontPeer (name
, attrs
);
593 fontCache
.put (keyMap
, newPeer
);
598 public ClasspathTextLayoutPeer
getClasspathTextLayoutPeer (AttributedString str
,
599 FontRenderContext frc
)
601 return new GdkTextLayout(str
, frc
);
604 protected EventQueue
getSystemEventQueueImpl()
606 synchronized (GtkToolkit
.class)
610 q
= new EventQueue();
611 GtkGenericPeer
.enableQueue (q
);
617 protected native void loadSystemColors (int[] systemColors
);
619 public DragSourceContextPeer
createDragSourceContextPeer(DragGestureEvent e
)
621 throw new Error("not implemented");
624 public Map
mapInputMethodHighlight(InputMethodHighlight highlight
)
626 throw new Error("not implemented");
629 public Rectangle
getBounds()
631 int[] dims
= new int[2];
632 getScreenSizeDimensions(dims
);
633 return new Rectangle(0, 0, dims
[0], dims
[1]);
636 // ClasspathToolkit methods
638 public GraphicsEnvironment
getLocalGraphicsEnvironment()
640 return new GdkGraphicsEnvironment();
643 public Font
createFont(int format
, InputStream stream
)
645 throw new UnsupportedOperationException();
648 public RobotPeer
createRobot (GraphicsDevice screen
) throws AWTException
650 return new GdkRobotPeer (screen
);
653 public void registerImageIOSpis(IIORegistry reg
)
655 GdkPixbufDecoder
.registerSpis(reg
);
658 public static native void gtkMain();
659 } // class GtkToolkit