1 /* GtkToolkit.java -- Implements an AWT Toolkit using GTK for peers
2 Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005, 2006
3 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
40 package gnu
.java
.awt
.peer
.gtk
;
42 import gnu
.classpath
.Configuration
;
43 import gnu
.java
.awt
.EmbeddedWindow
;
44 import gnu
.java
.awt
.peer
.ClasspathFontPeer
;
45 import gnu
.java
.awt
.peer
.ClasspathTextLayoutPeer
;
46 import gnu
.java
.awt
.peer
.EmbeddedWindowPeer
;
49 import java
.awt
.datatransfer
.Clipboard
;
50 import java
.awt
.dnd
.DragGestureEvent
;
51 import java
.awt
.dnd
.peer
.DragSourceContextPeer
;
52 import java
.awt
.font
.FontRenderContext
;
53 import java
.awt
.im
.InputMethodHighlight
;
54 import java
.awt
.image
.BufferedImage
;
55 import java
.awt
.image
.ColorModel
;
56 import java
.awt
.image
.DirectColorModel
;
57 import java
.awt
.image
.ImageConsumer
;
58 import java
.awt
.image
.ImageObserver
;
59 import java
.awt
.image
.ImageProducer
;
60 import java
.awt
.peer
.*;
61 import java
.io
.InputStream
;
63 import java
.text
.AttributedString
;
64 import java
.util
.HashMap
;
65 import java
.util
.HashSet
;
66 import java
.util
.Hashtable
;
67 import java
.util
.Iterator
;
68 import java
.util
.LinkedHashMap
;
70 import java
.util
.Properties
;
72 import javax
.imageio
.spi
.IIORegistry
;
74 /* This class uses a deprecated method java.awt.peer.ComponentPeer.getPeer().
75 This merits comment. We are basically calling Sun's bluff on this one.
76 We think Sun has deprecated it simply to discourage its use as it is
77 bad programming style. However, we need to get at a component's peer in
78 this class. If getPeer() ever goes away, we can implement a hash table
79 that will keep up with every window's peer, but for now this is faster. */
82 * This class accesses a system property called
83 * <tt>gnu.java.awt.peer.gtk.Graphics</tt>. If the property is defined and
84 * equal to "Graphics2D", the cairo-based GdkGraphics2D will be used in
85 * drawing contexts. Any other value will cause the older GdkGraphics
88 public class GtkToolkit
extends gnu
.java
.awt
.ClasspathToolkit
90 Hashtable containers
= new Hashtable();
92 static boolean useGraphics2dSet
;
93 static boolean useGraphics2d
;
94 static Thread mainThread
;
96 public static boolean useGraphics2D()
100 useGraphics2d
= System
.getProperty("gnu.java.awt.peer.gtk.Graphics",
101 "Graphics").equals("Graphics2D");
102 useGraphics2dSet
= true;
103 return useGraphics2d
;
106 static native void gtkInit(int portableNativeSync
);
110 if (Configuration
.INIT_LOAD_LIBRARY
)
111 System
.loadLibrary("gtkpeer");
113 int portableNativeSync
;
114 String portNatSyncProp
=
115 System
.getProperty("gnu.classpath.awt.gtk.portable.native.sync");
117 if (portNatSyncProp
== null)
118 portableNativeSync
= -1; // unset
119 else if (Boolean
.valueOf(portNatSyncProp
).booleanValue())
120 portableNativeSync
= 1; // true
122 portableNativeSync
= 0; // false
124 gtkInit(portableNativeSync
);
126 mainThread
= new Thread ("GTK main thread")
140 public native void beep();
141 private native void getScreenSizeDimensions(int[] xy
);
143 public int checkImage (Image image
, int width
, int height
,
144 ImageObserver observer
)
146 int status
= ImageObserver
.ALLBITS
147 | ImageObserver
.WIDTH
148 | ImageObserver
.HEIGHT
;
150 if (image
instanceof GtkImage
)
151 return ((GtkImage
) image
).checkImage (observer
);
153 if (observer
!= null)
154 observer
.imageUpdate (image
, status
,
156 image
.getWidth (observer
),
157 image
.getHeight (observer
));
163 * Helper to return either a Image -- the argument -- or a
164 * GtkImage with the errorLoading flag set if the argument is null.
166 private Image
imageOrError(Image b
)
169 return GtkImage
.getErrorImage();
174 public Image
createImage (String filename
)
176 if (filename
.length() == 0)
177 return new GtkImage ();
183 image
= GdkPixbufDecoder
.createBufferedImage(filename
);
185 image
= new GtkImage(filename
);
187 catch (IllegalArgumentException iae
)
191 return imageOrError(image
);
194 public Image
createImage (URL url
)
200 image
= GdkPixbufDecoder
.createBufferedImage(url
);
202 image
= new GtkImage(url
);
204 catch (IllegalArgumentException iae
)
208 return imageOrError(image
);
211 public Image
createImage (ImageProducer producer
)
217 image
= GdkPixbufDecoder
.createBufferedImage(producer
);
219 image
= new GtkImage(producer
);
221 catch (IllegalArgumentException iae
)
225 return imageOrError(image
);
228 public Image
createImage (byte[] imagedata
, int imageoffset
,
235 image
= GdkPixbufDecoder
.createBufferedImage(imagedata
,
240 byte[] datacopy
= new byte[imagelength
];
241 System
.arraycopy(imagedata
, imageoffset
, datacopy
, 0, imagelength
);
242 return new GtkImage(datacopy
);
245 catch (IllegalArgumentException iae
)
249 return imageOrError(image
);
253 * Creates an ImageProducer from the specified URL. The image is assumed
254 * to be in a recognised format.
256 * @param url URL to read image data from.
258 public ImageProducer
createImageProducer(URL url
)
260 return new GdkPixbufDecoder(url
);
264 * Returns the native color model (which isn't the same as the default
265 * ARGB color model, but doesn't have to be).
267 public ColorModel
getColorModel ()
269 /* Return the GDK-native ABGR format */
270 return new DirectColorModel(32,
277 public String
[] getFontList ()
279 return (new String
[] { "Dialog",
286 private class LRUCache
extends LinkedHashMap
289 public LRUCache(int max
)
291 super(max
, 0.75f
, true);
294 protected boolean removeEldestEntry(Map
.Entry eldest
)
296 return size() > max_entries
;
300 private LRUCache fontCache
= new LRUCache(50);
301 private LRUCache metricsCache
= new LRUCache(50);
302 private LRUCache imageCache
= new LRUCache(50);
304 public FontMetrics
getFontMetrics (Font font
)
306 synchronized (metricsCache
)
308 if (metricsCache
.containsKey(font
))
309 return (FontMetrics
) metricsCache
.get(font
);
312 FontMetrics m
= new GdkFontMetrics (font
);
313 synchronized (metricsCache
)
315 metricsCache
.put(font
, m
);
320 public Image
getImage (String filename
)
322 if (imageCache
.containsKey(filename
))
323 return (Image
) imageCache
.get(filename
);
326 Image im
= createImage(filename
);
327 imageCache
.put(filename
, im
);
332 public Image
getImage (URL url
)
334 if (imageCache
.containsKey(url
))
335 return (Image
) imageCache
.get(url
);
338 Image im
= createImage(url
);
339 imageCache
.put(url
, im
);
344 public PrintJob
getPrintJob (Frame frame
, String jobtitle
, Properties props
)
349 public native int getScreenResolution();
351 public Dimension
getScreenSize ()
353 int dim
[] = new int[2];
354 getScreenSizeDimensions(dim
);
355 return new Dimension(dim
[0], dim
[1]);
358 public Clipboard
getSystemClipboard()
360 SecurityManager secman
= System
.getSecurityManager();
362 secman
.checkSystemClipboardAccess();
364 return GtkClipboard
.getInstance();
368 * Prepares a GtkImage. For every other kind of Image it just
369 * assumes the image is already prepared for rendering.
371 public boolean prepareImage (Image image
, int width
, int height
,
372 ImageObserver observer
)
374 /* GtkImages are always prepared, as long as they're loaded. */
375 if (image
instanceof GtkImage
)
376 return ((((GtkImage
)image
).checkImage (observer
) &
377 ImageObserver
.ALLBITS
) != 0);
379 /* Assume anything else is too */
383 public native void sync();
385 protected void setComponentState (Component c
, GtkComponentPeer cp
)
387 /* Make the Component reflect Peer defaults */
388 if (c
.getForeground () == null)
389 c
.setForeground (cp
.getForeground ());
390 if (c
.getBackground () == null)
391 c
.setBackground (cp
.getBackground ());
392 // if (c.getFont () == null)
393 // c.setFont (cp.getFont ());
395 /* Make the Peer reflect the state of the Component */
396 if (! (c
instanceof Window
))
398 cp
.setCursor (c
.getCursor ());
400 Rectangle bounds
= c
.getBounds ();
401 cp
.setBounds (bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
);
402 cp
.setVisible (c
.isVisible ());
406 protected ButtonPeer
createButton (Button b
)
408 return new GtkButtonPeer (b
);
411 protected CanvasPeer
createCanvas (Canvas c
)
413 return new GtkCanvasPeer (c
);
416 protected CheckboxPeer
createCheckbox (Checkbox cb
)
418 return new GtkCheckboxPeer (cb
);
421 protected CheckboxMenuItemPeer
createCheckboxMenuItem (CheckboxMenuItem cmi
)
423 return new GtkCheckboxMenuItemPeer (cmi
);
426 protected ChoicePeer
createChoice (Choice c
)
428 return new GtkChoicePeer (c
);
431 protected DialogPeer
createDialog (Dialog d
)
433 return new GtkDialogPeer (d
);
436 protected FileDialogPeer
createFileDialog (FileDialog fd
)
438 return new GtkFileDialogPeer (fd
);
441 protected FramePeer
createFrame (Frame f
)
443 return new GtkFramePeer (f
);
446 protected LabelPeer
createLabel (Label label
)
448 return new GtkLabelPeer (label
);
451 protected ListPeer
createList (List list
)
453 return new GtkListPeer (list
);
456 protected MenuPeer
createMenu (Menu m
)
458 return new GtkMenuPeer (m
);
461 protected MenuBarPeer
createMenuBar (MenuBar mb
)
463 return new GtkMenuBarPeer (mb
);
466 protected MenuItemPeer
createMenuItem (MenuItem mi
)
468 return new GtkMenuItemPeer (mi
);
471 protected PanelPeer
createPanel (Panel p
)
473 return new GtkPanelPeer (p
);
476 protected PopupMenuPeer
createPopupMenu (PopupMenu target
)
478 return new GtkPopupMenuPeer (target
);
481 protected ScrollPanePeer
createScrollPane (ScrollPane sp
)
483 return new GtkScrollPanePeer (sp
);
486 protected ScrollbarPeer
createScrollbar (Scrollbar sb
)
488 return new GtkScrollbarPeer (sb
);
491 protected TextAreaPeer
createTextArea (TextArea ta
)
493 return new GtkTextAreaPeer (ta
);
496 protected TextFieldPeer
createTextField (TextField tf
)
498 return new GtkTextFieldPeer (tf
);
501 protected WindowPeer
createWindow (Window w
)
503 return new GtkWindowPeer (w
);
506 public EmbeddedWindowPeer
createEmbeddedWindow (EmbeddedWindow w
)
508 return new GtkEmbeddedWindowPeer (w
);
512 * @deprecated part of the older "logical font" system in earlier AWT
513 * implementations. Our newer Font class uses getClasspathFontPeer.
515 protected FontPeer
getFontPeer (String name
, int style
) {
516 // All fonts get a default size of 12 if size is not specified.
517 return getFontPeer(name
, style
, 12);
521 * Private method that allows size to be set at initialization time.
523 private FontPeer
getFontPeer (String name
, int style
, int size
)
525 Map attrs
= new HashMap ();
526 ClasspathFontPeer
.copyStyleToAttrs (style
, attrs
);
527 ClasspathFontPeer
.copySizeToAttrs (size
, attrs
);
528 return getClasspathFontPeer (name
, attrs
);
532 * Newer method to produce a peer for a Font object, even though Sun's
533 * design claims Font should now be peerless, we do not agree with this
534 * model, hence "ClasspathFontPeer".
537 public ClasspathFontPeer
getClasspathFontPeer (String name
, Map attrs
)
539 Map keyMap
= new HashMap (attrs
);
540 // We don't know what kind of "name" the user requested (logical, face,
541 // family), and we don't actually *need* to know here. The worst case
542 // involves failure to consolidate fonts with the same backend in our
543 // cache. This is harmless.
544 keyMap
.put ("GtkToolkit.RequestedFontName", name
);
545 if (fontCache
.containsKey (keyMap
))
546 return (ClasspathFontPeer
) fontCache
.get (keyMap
);
549 ClasspathFontPeer newPeer
= new GdkFontPeer (name
, attrs
);
550 fontCache
.put (keyMap
, newPeer
);
555 public ClasspathTextLayoutPeer
getClasspathTextLayoutPeer (AttributedString str
,
556 FontRenderContext frc
)
558 return new GdkTextLayout(str
, frc
);
561 protected EventQueue
getSystemEventQueueImpl()
563 synchronized (GtkToolkit
.class)
567 q
= new EventQueue();
573 protected native void loadSystemColors (int[] systemColors
);
575 public DragSourceContextPeer
createDragSourceContextPeer(DragGestureEvent e
)
577 throw new Error("not implemented");
580 public Map
mapInputMethodHighlight(InputMethodHighlight highlight
)
582 throw new Error("not implemented");
585 public Rectangle
getBounds()
587 int[] dims
= new int[2];
588 getScreenSizeDimensions(dims
);
589 return new Rectangle(0, 0, dims
[0], dims
[1]);
592 // ClasspathToolkit methods
594 public GraphicsEnvironment
getLocalGraphicsEnvironment()
596 return new GdkGraphicsEnvironment();
599 public Font
createFont(int format
, InputStream stream
)
601 throw new UnsupportedOperationException();
604 public RobotPeer
createRobot (GraphicsDevice screen
) throws AWTException
606 return new GdkRobotPeer (screen
);
609 public void registerImageIOSpis(IIORegistry reg
)
611 GdkPixbufDecoder
.registerSpis(reg
);
614 public static native void gtkMain();
615 } // class GtkToolkit