001    /* Toolkit.java -- AWT Toolkit superclass
002       Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
003       Free Software Foundation, Inc.
004    
005    This file is part of GNU Classpath.
006    
007    GNU Classpath is free software; you can redistribute it and/or modify
008    it under the terms of the GNU General Public License as published by
009    the Free Software Foundation; either version 2, or (at your option)
010    any later version.
011    
012    GNU Classpath is distributed in the hope that it will be useful, but
013    WITHOUT ANY WARRANTY; without even the implied warranty of
014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015    General Public License for more details.
016    
017    You should have received a copy of the GNU General Public License
018    along with GNU Classpath; see the file COPYING.  If not, write to the
019    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
020    02110-1301 USA.
021    
022    Linking this library statically or dynamically with other modules is
023    making a combined work based on this library.  Thus, the terms and
024    conditions of the GNU General Public License cover the whole
025    combination.
026    
027    As a special exception, the copyright holders of this library give you
028    permission to link this library with independent modules to produce an
029    executable, regardless of the license terms of these independent
030    modules, and to copy and distribute the resulting executable under
031    terms of your choice, provided that you also meet, for each linked
032    independent module, the terms and conditions of the license of that
033    module.  An independent module is a module which is not derived from
034    or based on this library.  If you modify this library, you may extend
035    this exception to your version of the library, but you are not
036    obligated to do so.  If you do not wish to do so, delete this
037    exception statement from your version. */
038    
039    
040    package java.awt;
041    
042    import gnu.classpath.SystemProperties;
043    import gnu.java.awt.AWTUtilities;
044    import gnu.java.awt.peer.GLightweightPeer;
045    import gnu.java.awt.peer.headless.HeadlessToolkit;
046    
047    import java.awt.datatransfer.Clipboard;
048    import java.awt.dnd.DragGestureEvent;
049    import java.awt.dnd.DragGestureListener;
050    import java.awt.dnd.DragGestureRecognizer;
051    import java.awt.dnd.DragSource;
052    import java.awt.dnd.peer.DragSourceContextPeer;
053    import java.awt.event.AWTEventListener;
054    import java.awt.event.AWTEventListenerProxy;
055    import java.awt.event.KeyEvent;
056    import java.awt.font.TextAttribute;
057    import java.awt.im.InputMethodHighlight;
058    import java.awt.image.ColorModel;
059    import java.awt.image.ImageObserver;
060    import java.awt.image.ImageProducer;
061    import java.awt.peer.ButtonPeer;
062    import java.awt.peer.CanvasPeer;
063    import java.awt.peer.CheckboxMenuItemPeer;
064    import java.awt.peer.CheckboxPeer;
065    import java.awt.peer.ChoicePeer;
066    import java.awt.peer.DesktopPeer;
067    import java.awt.peer.DialogPeer;
068    import java.awt.peer.FileDialogPeer;
069    import java.awt.peer.FontPeer;
070    import java.awt.peer.FramePeer;
071    import java.awt.peer.LabelPeer;
072    import java.awt.peer.LightweightPeer;
073    import java.awt.peer.ListPeer;
074    import java.awt.peer.MenuBarPeer;
075    import java.awt.peer.MenuItemPeer;
076    import java.awt.peer.MenuPeer;
077    import java.awt.peer.MouseInfoPeer;
078    import java.awt.peer.PanelPeer;
079    import java.awt.peer.PopupMenuPeer;
080    import java.awt.peer.ScrollPanePeer;
081    import java.awt.peer.ScrollbarPeer;
082    import java.awt.peer.TextAreaPeer;
083    import java.awt.peer.TextFieldPeer;
084    import java.awt.peer.WindowPeer;
085    import java.beans.PropertyChangeListener;
086    import java.beans.PropertyChangeSupport;
087    import java.io.File;
088    import java.io.FileInputStream;
089    import java.net.URL;
090    import java.security.AccessController;
091    import java.security.PrivilegedAction;
092    import java.util.ArrayList;
093    import java.util.Hashtable;
094    import java.util.Map;
095    import java.util.Properties;
096    import java.util.StringTokenizer;
097    
098    /**
099     * The AWT system uses a set of native peer objects to implement its
100     * widgets.  These peers are provided by a peer toolkit, that is accessed
101     * via a subclass of this superclass.  The system toolkit is retrieved
102     * by the static methods <code>getDefaultToolkit</code>.  This method
103     * determines the system toolkit by examining the system property
104     * <code>awt.toolkit</code>.  That property is set to the name of the
105     * <code>Toolkit</code> subclass for the specified peer set.  If the
106     * <code>awt.toolkit</code> property is not set, then the default
107     * toolkit <code>gnu.java.awt.peer.gtk.GtkToolkit</code> is used.  This
108     * toolkit creates its peers using the GTK+ toolkit.
109     *
110     * @author Aaron M. Renn (arenn@urbanophile.com)
111     */
112    public abstract class Toolkit
113    {
114      /** The default toolkit name. */
115      private static String default_toolkit_name
116        = gnu.classpath.Configuration.default_awt_peer_toolkit;
117    
118      /**
119       * The toolkit in use.  Once we load it, we don't ever change it
120       * if the awt.toolkit property is set.
121       */
122      private static Toolkit toolkit;
123    
124      /** The toolkit properties. */
125      private static Properties props = new Properties();
126    
127      protected final Map<String,Object> desktopProperties = 
128        new Hashtable<String,Object>();
129    
130      protected final PropertyChangeSupport desktopPropsSupport
131        = new PropertyChangeSupport(this);
132    
133      /**
134       * All registered AWTEventListener objects. This is package private, so the
135       * event queue can efficiently access this list.
136       */
137      AWTEventListenerProxy[] awtEventListeners;
138    
139      /**
140       * The shared peer for all lightweight components.
141       */
142      private GLightweightPeer lightweightPeer;
143    
144      /**
145       * Default constructor for subclasses.
146       */
147      public Toolkit()
148      {
149        awtEventListeners = new AWTEventListenerProxy[0];
150      }
151    
152      /**
153       * 
154       * @param target
155       * @return
156       * @throws HeadlessException
157       */
158      protected abstract DesktopPeer createDesktopPeer(Desktop target)
159        throws HeadlessException;
160      
161      /**
162       * Creates a peer object for the specified <code>Button</code>.
163       *
164       * @param target The <code>Button</code> to create the peer for.
165       * 
166       * @return The peer for the specified <code>Button</code> object.
167       *
168       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
169       */
170      protected abstract ButtonPeer createButton(Button target);
171    
172      /**
173       * Creates a peer object for the specified <code>TextField</code>.
174       *
175       * @param target The <code>TextField</code> to create the peer for.
176       *
177       * @return The peer for the specified <code>TextField</code> object.
178       *
179       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
180       */
181      protected abstract TextFieldPeer createTextField(TextField target);
182    
183      /**
184       * Creates a peer object for the specified <code>Label</code>.
185       *
186       * @param target The <code>Label</code> to create the peer for.
187       *
188       * @return The peer for the specified <code>Label</code> object.
189       *
190       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
191       */
192      protected abstract LabelPeer createLabel(Label target);
193    
194      /**
195       * Creates a peer object for the specified <code>List</code>.
196       *
197       * @param target The <code>List</code> to create the peer for.
198       *
199       * @return The peer for the specified <code>List</code> object.
200       *
201       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
202       */
203      protected abstract ListPeer createList(List target);
204    
205      /**
206       * Creates a peer object for the specified <code>Checkbox</code>.
207       *
208       * @param target The <code>Checkbox</code> to create the peer for.
209       *
210       * @return The peer for the specified <code>Checkbox</code> object.
211       *
212       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
213       */
214      protected abstract CheckboxPeer createCheckbox(Checkbox target);
215    
216      /**
217       * Creates a peer object for the specified <code>Scrollbar</code>.
218       *
219       * @param target The <code>Scrollbar</code> to create the peer for.
220       *
221       * @return The peer for the specified <code>Scrollbar</code> object.
222       *
223       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
224       */
225      protected abstract ScrollbarPeer createScrollbar(Scrollbar target);
226    
227      /**
228       * Creates a peer object for the specified <code>ScrollPane</code>.
229       *
230       * @param target The <code>ScrollPane</code> to create the peer for.
231       *
232       * @return The peer for the specified <code>ScrollPane</code> object.
233       *
234       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
235       */
236      protected abstract ScrollPanePeer createScrollPane(ScrollPane target);
237    
238      /**
239       * Creates a peer object for the specified <code>TextArea</code>.
240       *
241       * @param target The <code>TextArea</code> to create the peer for.
242       *
243       * @return The peer for the specified <code>TextArea</code> object.
244       *
245       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
246       */
247      protected abstract TextAreaPeer createTextArea(TextArea target);
248    
249      /**
250       * Creates a peer object for the specified <code>Choice</code>.
251       *
252       * @param target The <code>Choice</code> to create the peer for.
253       *
254       * @return The peer for the specified <code>Choice</code> object.
255       *
256       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
257       */
258      protected abstract ChoicePeer createChoice(Choice target);
259    
260      /**
261       * Creates a peer object for the specified <code>Frame</code>.
262       *
263       * @param target The <code>Frame</code> to create the peer for.
264       *
265       * @return The peer for the specified <code>Frame</code> object.
266       *
267       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
268       */
269      protected abstract FramePeer createFrame(Frame target);
270    
271      /**
272       * Creates a peer object for the specified <code>Canvas</code>.
273       *
274       * @param target The <code>Canvas</code> to create the peer for.
275       *
276       * @return The peer for the specified <code>Canvas</code> object.
277       */
278      protected abstract CanvasPeer createCanvas(Canvas target);
279    
280      /**
281       * Creates a peer object for the specified <code>Panel</code>.
282       *
283       * @param target The <code>Panel</code> to create the peer for.
284       *
285       * @return The peer for the specified <code>Panel</code> object.
286       */
287      protected abstract PanelPeer createPanel(Panel target);
288    
289      /**
290       * Creates a peer object for the specified <code>Window</code>.
291       *
292       * @param target The <code>Window</code> to create the peer for.
293       *
294       * @return The peer for the specified <code>Window</code> object.
295       *
296       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
297       */
298      protected abstract WindowPeer createWindow(Window target);
299    
300      /**
301       * Creates a peer object for the specified <code>Dialog</code>.
302       *
303       * @param target The dialog to create the peer for
304       *
305       * @return The peer for the specified font name.
306       *
307       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
308       */
309      protected abstract DialogPeer createDialog(Dialog target);
310    
311      /**
312       * Creates a peer object for the specified <code>MenuBar</code>.
313       *
314       * @param target The <code>MenuBar</code> to create the peer for.
315       *
316       * @return The peer for the specified <code>MenuBar</code> object.
317       *
318       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
319       */
320      protected abstract MenuBarPeer createMenuBar(MenuBar target);
321    
322      /**
323       * Creates a peer object for the specified <code>Menu</code>.
324       *
325       * @param target The <code>Menu</code> to create the peer for.
326       *
327       * @return The peer for the specified <code>Menu</code> object.
328       *
329       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
330       */
331      protected abstract MenuPeer createMenu(Menu target);
332    
333      /**
334       * Creates a peer object for the specified <code>PopupMenu</code>.
335       *
336       * @param target The <code>PopupMenu</code> to create the peer for.
337       *
338       * @return The peer for the specified <code>PopupMenu</code> object.
339       *
340       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
341       */
342      protected abstract PopupMenuPeer createPopupMenu(PopupMenu target);
343    
344      /**
345       * Creates a peer object for the specified <code>MenuItem</code>.
346       *
347       * @param target The <code>MenuItem</code> to create the peer for.
348       *
349       * @return The peer for the specified <code>MenuItem</code> object.
350       *
351       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
352       */
353      protected abstract MenuItemPeer createMenuItem(MenuItem target);
354    
355      /**
356       * Returns a MouseInfoPeer. 
357       * The default implementation of this method throws
358       * UnsupportedOperationException.
359       *
360       * Toolkit implementations should overload this if possible, however.
361       */
362      protected MouseInfoPeer getMouseInfoPeer()
363      {
364        throw new UnsupportedOperationException("No mouse info peer.");
365      }
366    
367      /**
368       * Creates a peer object for the specified <code>FileDialog</code>.
369       *
370       * @param target The <code>FileDialog</code> to create the peer for.
371       *
372       * @return The peer for the specified <code>FileDialog</code> object.
373       *
374       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
375       */
376      protected abstract FileDialogPeer createFileDialog(FileDialog target);
377    
378      /**
379       * Creates a peer object for the specified <code>CheckboxMenuItem</code>.
380       *
381       * @param target The <code>CheckboxMenuItem</code> to create the peer for.
382       *
383       * @return The peer for the specified <code>CheckboxMenuItem</code> object.
384       *
385       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
386       */
387      protected abstract CheckboxMenuItemPeer
388        createCheckboxMenuItem(CheckboxMenuItem target);
389    
390      /**
391       * Creates a peer object for the specified <code>Component</code>.  The
392       * peer returned by this method is not a native windowing system peer
393       * with its own native window.  Instead, this method allows the component
394       * to draw on its parent window as a "lightweight" widget.
395       *
396       * @param target The <code>Component</code> to create the peer for.
397       *
398       * @return The peer for the specified <code>Component</code> object.
399       */
400      protected LightweightPeer createComponent(Component target)
401      {
402        if (lightweightPeer == null)
403          lightweightPeer = new GLightweightPeer();
404        return lightweightPeer;
405      }
406    
407      /**
408       * Creates a peer object for the specified font name.
409       *
410       * @param name The font to create the peer for.
411       * @param style The font style to create the peer for.
412       *
413       * @return The peer for the specified font name.
414       *
415       * @deprecated
416       */
417      protected abstract FontPeer getFontPeer(String name, int style);
418    
419      /**
420       * Copies the current system colors into the specified array.  This is
421       * the interface used by the <code>SystemColor</code> class.  Although
422       * this method fills in the array with some default colors a real Toolkit
423       * should override this method and provide real system colors for the
424       * native GUI platform.
425       *
426       * @param systemColors The array to copy the system colors into.
427       * It must be at least 26 elements.
428       *
429       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
430       *
431       * @see java.awt.SystemColor
432       */
433      protected void loadSystemColors(int systemColors[])
434      {
435        systemColors[SystemColor.DESKTOP]                 = 0xFF005C5C;
436        systemColors[SystemColor.ACTIVE_CAPTION]          = 0xFF000080;
437        systemColors[SystemColor.ACTIVE_CAPTION_TEXT]     = 0xFFFFFFFF;
438        systemColors[SystemColor.ACTIVE_CAPTION_BORDER]   = 0xFFC0C0C0;
439        systemColors[SystemColor.INACTIVE_CAPTION]        = 0xFF808080;
440        systemColors[SystemColor.INACTIVE_CAPTION_TEXT]   = 0xFFC0C0C0;
441        systemColors[SystemColor.INACTIVE_CAPTION_BORDER] = 0xFFC0C0C0;
442        systemColors[SystemColor.WINDOW]                  = 0xFFFFFFFF;
443        systemColors[SystemColor.WINDOW_BORDER]           = 0xFF000000;
444        systemColors[SystemColor.WINDOW_TEXT]             = 0xFF000000;
445        systemColors[SystemColor.MENU]                    = 0xFFC0C0C0;
446        systemColors[SystemColor.MENU_TEXT]               = 0xFF000000;
447        systemColors[SystemColor.TEXT]                    = 0xFFC0C0C0;
448        systemColors[SystemColor.TEXT_TEXT]               = 0xFF000000;
449        systemColors[SystemColor.TEXT_HIGHLIGHT]          = 0xFF000090;
450        systemColors[SystemColor.TEXT_HIGHLIGHT_TEXT]     = 0xFFFFFFFF;
451        systemColors[SystemColor.TEXT_INACTIVE_TEXT]      = 0xFF808080;
452        systemColors[SystemColor.CONTROL]                 = 0xFFC0C0C0;
453        systemColors[SystemColor.CONTROL_TEXT]            = 0xFF000000;
454        systemColors[SystemColor.CONTROL_HIGHLIGHT]       = 0xFFFFFFFF;
455        systemColors[SystemColor.CONTROL_LT_HIGHLIGHT]    = 0xFFE0E0E0;
456        systemColors[SystemColor.CONTROL_SHADOW]          = 0xFF808080;
457        systemColors[SystemColor.CONTROL_DK_SHADOW]       = 0xFF000000;
458        systemColors[SystemColor.SCROLLBAR]               = 0xFFE0E0E0;
459        systemColors[SystemColor.INFO]                    = 0xFFE0E000;
460        systemColors[SystemColor.INFO_TEXT]               = 0xFF000000;
461      }
462    
463      /**
464       * @since 1.4
465       *
466       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
467       */
468      public void setDynamicLayout(boolean dynamic)
469      {
470      }
471    
472      /**
473       * @since 1.4
474       *
475       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
476       */
477      protected boolean isDynamicLayoutSet()
478      {
479        return false;
480      }
481    
482      /**
483       * @since 1.4
484       *
485       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
486       */
487      public boolean isDynamicLayoutActive()
488      {
489        return false;
490      }
491    
492      /**
493       * Returns the dimensions of the screen in pixels.
494       *
495       * @return The dimensions of the screen in pixels.
496       * 
497       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
498       */
499      public abstract Dimension getScreenSize();
500    
501      /**
502       * Returns the screen resolution in dots per square inch.
503       *
504       * @return The screen resolution in dots per square inch.
505       *
506       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
507       */
508      public abstract int getScreenResolution();
509    
510      /**
511       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
512       *
513       * @since 1.4
514       */
515      public Insets getScreenInsets(GraphicsConfiguration gc)
516      {
517        return new Insets(0, 0, 0, 0);
518      }
519    
520      /**
521       * Returns the color model of the screen.
522       *
523       * @return The color model of the screen.
524       * 
525       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
526       */
527      public abstract ColorModel getColorModel();
528    
529      /**
530       * Returns the names of the available fonts.
531       *
532       * @return The names of the available fonts.
533       *
534       * @deprecated
535       */
536      public abstract String[] getFontList();
537    
538      /**
539       * Return the font metrics for the specified font
540       *
541       * @param name The name of the font to return metrics for.
542       *
543       * @return The requested font metrics.
544       *
545       * @deprecated
546       */
547      public abstract FontMetrics getFontMetrics(Font name);
548    
549      /**
550       * Flushes any buffered data to the screen so that it is in sync with
551       * what the AWT system has drawn to it.
552       */
553      public abstract void sync();
554    
555      /**
556       * Returns an instance of the default toolkit.  The default toolkit is
557       * the subclass of <code>Toolkit</code> specified in the system property
558       * <code>awt.toolkit</code>, or <code>gnu.java.awt.peer.gtk.GtkToolkit</code>
559       * if the property is not set.
560       *
561       * @return An instance of the system default toolkit.
562       *
563       * @throws AWTError If the toolkit cannot be loaded.
564       */
565      public static synchronized Toolkit getDefaultToolkit()
566      {
567        if (toolkit != null)
568          return toolkit;
569    
570        String toolkit_name = SystemProperties.getProperty("awt.toolkit",
571                                                           default_toolkit_name);
572        try
573          {
574            ClassLoader cl;
575            cl = (ClassLoader) AccessController.doPrivileged
576            (new PrivilegedAction()
577              {
578                public Object run()
579                  {
580                    return ClassLoader.getSystemClassLoader();
581                  }
582              });
583            Class cls = Class.forName(toolkit_name, true, cl);
584            Object obj = cls.newInstance();
585            if (!(obj instanceof Toolkit))
586              throw new AWTError(toolkit_name + " is not a subclass of " +
587                                 "java.awt.Toolkit");
588            toolkit = (Toolkit) obj;
589    
590            initAccessibility();
591            return toolkit;
592          }
593        catch (ThreadDeath death)
594          {
595            throw death;
596          }
597        catch (Throwable t)
598          {
599            // Check for the headless property.
600            if (GraphicsEnvironment.isHeadless())
601              {
602                toolkit = new HeadlessToolkit();
603                return toolkit;
604              }
605            else
606              {
607                AWTError e = new AWTError("Cannot load AWT toolkit: "
608                                          + toolkit_name);
609                throw (AWTError) e.initCause(t);
610              }
611          }
612      }
613    
614      /**
615       * Returns an image from the specified file, which must be in a
616       * recognized format.  Supported formats vary from toolkit to toolkit.
617       *
618       * @return name The name of the file to read the image from.
619       */
620      public abstract Image getImage(String name);
621    
622      /**
623       * Returns an image from the specified URL, which must be in a
624       * recognized format.  Supported formats vary from toolkit to toolkit.
625       *
626       * @return url The URl to read the image from.
627       */
628      public abstract Image getImage(URL url);
629    
630      public abstract Image createImage(String filename);
631    
632      public abstract Image createImage(URL url);
633    
634      /**
635       * Readies an image to be rendered on the screen.  The width and height
636       * values can be set to the default sizes for the image by passing -1
637       * in those parameters.
638       *
639       * @param image The image to prepare for rendering.
640       * @param width The width of the image.
641       * @param height The height of the image.
642       * @param observer The observer to receive events about the preparation
643       * process.
644       *
645       * @return <code>true</code> if the image is already prepared for rendering,
646       * <code>false</code> otherwise.
647       */
648      public abstract boolean prepareImage(Image image, int width, int height,
649                                           ImageObserver observer);
650    
651      /**
652       * Checks the status of specified image as it is being readied for
653       * rendering.
654       *
655       * @param image The image to prepare for rendering.
656       * @param width The width of the image.
657       * @param height The height of the image.
658       * @param observer The observer to receive events about the preparation
659       * process.
660       *
661       * @return A union of the bitmasks from
662       * <code>java.awt.image.ImageObserver</code> that indicates the current
663       * state of the imaging readying process.
664       */
665      public abstract int checkImage(Image image, int width, int height,
666                                     ImageObserver observer);
667    
668      /**
669       * Creates an image using the specified <code>ImageProducer</code>
670       *
671       * @param producer The <code>ImageProducer</code> to create the image from.
672       *
673       * @return The created image.
674       */
675      public abstract Image createImage(ImageProducer producer);
676    
677      /**
678       * Creates an image from the specified byte array. The array must be in
679       * a recognized format.  Supported formats vary from toolkit to toolkit.
680       *
681       * @param data The raw image data.
682       *
683       * @return The created image.
684       */
685      public Image createImage(byte[] data)
686      {
687        return createImage(data, 0, data.length);
688      }
689    
690      /**
691       * Creates an image from the specified portion of the byte array passed.
692       * The array must be in a recognized format.  Supported formats vary from
693       * toolkit to toolkit.
694       *
695       * @param data The raw image data.
696       * @param offset The offset into the data where the image data starts.
697       * @param len The length of the image data.
698       *
699       * @return The created image.
700       */
701      public abstract Image createImage(byte[] data, int offset, int len);
702    
703      /**
704       * Returns a instance of <code>PrintJob</code> for the specified
705       * arguments.
706       *
707       * @param frame The window initiating the print job.
708       * @param title The print job title.
709       * @param props The print job properties.
710       *
711       * @return The requested print job, or <code>null</code> if the job
712       * was cancelled.
713       *
714       * @exception NullPointerException If frame is null,
715       * or GraphicsEnvironment.isHeadless() returns true.
716       * @exception SecurityException If this thread is not allowed to initiate
717       * a print job request.
718       */
719      public abstract PrintJob getPrintJob(Frame frame, String title,
720                                           Properties props);
721    
722      /**
723       * Returns a instance of <code>PrintJob</code> for the specified
724       * arguments.
725       *
726       * @param frame The window initiating the print job.
727       * @param title The print job title.
728       * @param jobAttr A set of job attributes which will control the print job.
729       * @param pageAttr A set of page attributes which will control the print job.
730       *
731       * @exception NullPointerException If frame is null, and either jobAttr is null
732       * or jobAttr.getDialog() returns JobAttributes.DialogType.NATIVE.
733       * @exception IllegalArgumentException If pageAttrspecifies differing cross
734       * feed and feed resolutions, or when GraphicsEnvironment.isHeadless() returns
735       * true.
736       * @exception SecurityException If this thread is not allowed to initiate
737       * a print job request.
738       *
739       * @since 1.3
740       */
741      public PrintJob getPrintJob(Frame frame, String title,
742                                  JobAttributes jobAttr, PageAttributes pageAttr)
743      {
744        // FIXME: it is possible this check may be removed
745        // if this method, when written, always delegates to
746        // getPrintJob(Frame, String, Properties).
747        SecurityManager sm;
748        sm = System.getSecurityManager();
749        if (sm != null)
750          sm.checkPrintJobAccess();
751    
752        return null;
753      }
754    
755      /**
756       * Causes a "beep" tone to be generated.
757       */
758      public abstract void beep();
759    
760      /**
761       * Returns the system clipboard.
762       *
763       * @return THe system clipboard.
764       *
765       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
766       */
767      public abstract Clipboard getSystemClipboard();
768    
769      /**
770       * Gets the singleton instance of the system selection as a
771       * Clipboard object. The system selection contains the selected text
772       * of the last component/widget that had focus and a text selection.
773       * The default implementation returns null.
774       *
775       * @return The Clipboard holding the system (text) selection or null
776       * if the Toolkit or system doesn't support a selection clipboard.
777       *
778       * @exception HeadlessException If GraphicsEnvironment.isHeadless()
779       * is true.
780       * @exception SecurityException If the current security manager
781       * checkSystemClipboardAccess() doesn't allow access.
782       *
783       * @since 1.4
784       */
785      public Clipboard getSystemSelection()
786      {
787        return null;
788      }
789    
790      /**
791       * Returns the accelerator key mask for menu shortcuts. The default is
792       * <code>Event.CTRL_MASK</code>.  A toolkit must override this method
793       * to change the default.
794       *
795       * @return The key mask for the menu accelerator key.
796       *
797       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
798       */
799      public int getMenuShortcutKeyMask()
800      {
801        return Event.CTRL_MASK;
802      }
803    
804      /**
805       * Returns whether the given locking key on the keyboard is currently in its
806       * "on" state.
807       *
808       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
809       * @exception IllegalArgumentException If keyCode is not one of the valid keys.
810       * @exception UnsupportedOperationException If the host system doesn't allow
811       * getting the state of this key programmatically, or if the keyboard doesn't
812       * have this key.
813       */
814      public boolean getLockingKeyState(int keyCode)
815      {
816        if (AWTUtilities.isValidKey(keyCode))
817          throw new UnsupportedOperationException
818            ("cannot get locking state of key code " + keyCode);
819    
820        throw new IllegalArgumentException("invalid key code " + keyCode);
821      }
822    
823      /**
824       * Sets the state of the given locking key on the keyboard.
825       *
826       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
827       * @exception IllegalArgumentException If keyCode is not one of the valid keys.
828       * @exception UnsupportedOperationException If the host system doesn't allow
829       * getting the state of this key programmatically, or if the keyboard doesn't
830       * have this key.
831       */
832      public void setLockingKeyState(int keyCode, boolean on)
833      {
834        if (keyCode != KeyEvent.VK_CAPS_LOCK
835            && keyCode != KeyEvent.VK_NUM_LOCK
836            && keyCode != KeyEvent.VK_SCROLL_LOCK)
837          throw new IllegalArgumentException();
838        
839        throw new UnsupportedOperationException();
840      }
841    
842      /**
843       * Returns the native container object of the specified component.  This
844       * method is necessary because the parent component might be a lightweight
845       * component.
846       *
847       * @param component The component to fetch the native container for.
848       *
849       * @return The native container object for this component.
850       */
851      protected static Container getNativeContainer(Component component)
852      {
853        component = component.getParent();
854        while (true)
855          {
856            if (component == null)
857              return null;
858            if (! (component instanceof Container))
859              {
860                component = component.getParent();
861                continue;
862              }
863            if (component.getPeer() instanceof LightweightPeer)
864              {
865                component = component.getParent();
866                continue;
867              }
868            return (Container) component;
869          }
870      }
871    
872      /**
873       * Creates a new custom cursor object.
874       *
875       * @exception IndexOutOfBoundsException If the hotSpot values are outside
876       * the bounds of the cursor.
877       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
878       */
879      public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
880      {
881        // Presumably the only reason this isn't abstract is for backwards
882        // compatibility? FIXME?
883        if (GraphicsEnvironment.isHeadless())
884          throw new HeadlessException("No custom cursor in an headless graphics "
885                                      + "environment.");
886        return null;
887      }
888    
889      /**
890       * Returns the supported cursor dimension which is closest to the
891       * desired sizes.
892       *
893       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
894       */
895      public Dimension getBestCursorSize(int preferredWidth, int preferredHeight)
896      {
897        if (GraphicsEnvironment.isHeadless())
898          throw new HeadlessException("No best cursor size in an headless "
899                                      + "graphics environment.");
900        return new Dimension (0,0);
901      }
902    
903      /**
904       * Returns the maximum number of colors the Toolkit supports in a custom
905       * cursor palette.
906       *
907       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
908       */
909      public int getMaximumCursorColors()
910      {
911        return 0;
912      }
913    
914      /**
915       * Returns whether Toolkit supports this state for Frames.
916       *
917       * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
918       * 
919       * @since 1.4
920       */
921      public boolean isFrameStateSupported(int state)
922      {
923        return false;
924      }
925    
926      /**
927       * Returns the value of the property with the specified name, or the
928       * default value if the property does not exist.
929       *
930       * @param key The name of the property to retrieve.
931       * @param def The default value of the property.
932       */
933      public static String getProperty(String key, String def)
934      {
935        return props.getProperty(key, def);
936      }
937    
938    
939      /**
940       * Returns the event queue that is suitable for the calling context.
941       *
942       * <p>Despite the word &#x201c;System&#x201d; in the name of this
943       * method, a toolkit may provide different event queues for each
944       * applet. There is no guarantee that the same queue is shared
945       * system-wide.
946       *
947       * <p>The implementation first checks whether a
948       * SecurityManager has been installed. If so, its {@link
949       * java.lang.SecurityManager#checkAwtEventQueueAccess()} method gets
950       * called. The security manager will throw a SecurityException if it
951       * does not grant the permission to access the event queue.
952       *
953       * <p>Next, the call is delegated to {@link
954       * #getSystemEventQueueImpl()}.
955       *
956       * @return The event queue for this applet (or application).
957       *
958       * @throws SecurityException if a security manager has been
959       * installed, and it does not grant the permission to access the
960       * event queue.
961       */
962      public final EventQueue getSystemEventQueue()
963      {
964        SecurityManager sm;
965    
966        sm = System.getSecurityManager();
967        if (sm != null)
968          sm.checkAwtEventQueueAccess();
969    
970        return getSystemEventQueueImpl();
971      }
972    
973    
974      /**
975       * Returns the event queue that is suitable for the calling context.
976       *
977       * <p>Despite the word &#x201c;System&#x201d; in the name of this
978       * method, a toolkit may provide different event queues for each
979       * applet. There is no guarantee that the same queue is shared
980       * system-wide.
981       *
982       * <p>No security checks are performed, which is why this method
983       * may only be called by Toolkits.
984       *
985       * @see #getSystemEventQueue()
986       */
987      protected abstract EventQueue getSystemEventQueueImpl();
988    
989    
990      /**
991       * @since 1.3
992       */
993      public abstract DragSourceContextPeer
994        createDragSourceContextPeer(DragGestureEvent e);
995    
996      /**
997       * @since 1.3
998       */
999      public <T extends DragGestureRecognizer> T
1000        createDragGestureRecognizer(Class<T> recognizer, DragSource ds,
1001                                    Component comp, int actions,
1002                                    DragGestureListener l)
1003      {
1004        return null;
1005      }
1006    
1007      public final Object getDesktopProperty(String propertyName)
1008      {
1009        return desktopProperties.get(propertyName);
1010      }
1011    
1012      protected final void setDesktopProperty(String name, Object newValue)
1013      {
1014        Object oldValue = getDesktopProperty(name);
1015        desktopProperties.put(name, newValue);
1016        desktopPropsSupport.firePropertyChange(name, oldValue, newValue);
1017      }
1018    
1019      protected Object lazilyLoadDesktopProperty(String name)
1020      {
1021        // FIXME - what is this??
1022        return null;
1023      }
1024    
1025      protected void initializeDesktopProperties()
1026      {
1027        // Overridden by toolkit implementation?
1028      }
1029    
1030      public void addPropertyChangeListener(String name,
1031                                            PropertyChangeListener pcl)
1032      {
1033        desktopPropsSupport.addPropertyChangeListener(name, pcl);
1034      }
1035    
1036      public void removePropertyChangeListener(String name,
1037                                               PropertyChangeListener pcl)
1038      {
1039        desktopPropsSupport.removePropertyChangeListener(name, pcl);
1040      }
1041    
1042      /**
1043       * @since 1.4
1044       */
1045      public PropertyChangeListener[] getPropertyChangeListeners()
1046      {
1047        return desktopPropsSupport.getPropertyChangeListeners();
1048      }
1049    
1050      /**
1051       * @since 1.4
1052       */
1053      public PropertyChangeListener[] getPropertyChangeListeners(String name)
1054      {
1055        return desktopPropsSupport.getPropertyChangeListeners(name);
1056      }
1057    
1058      /**
1059       * Adds an AWTEventListener to this toolkit. This listener is informed about
1060       * all events that pass the eventqueue that match the specified
1061       * <code>evenMask</code>. The <code>eventMask</code> is an ORed combination
1062       * of event masks as defined in {@link AWTEvent}.
1063       *
1064       * If a security manager is installed, it is asked first if an
1065       * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
1066       * This may result in a <code>SecurityException</code> beeing thrown.
1067       *
1068       * It is not recommended to use this kind of notification for normal
1069       * applications. It is intended solely for the purpose of debugging and to
1070       * support special facilities.
1071       *
1072       * @param listener the listener to add
1073       * @param eventMask the event mask of event types which the listener is
1074       *        interested in
1075       *
1076       * @since 1.2
1077       *
1078       * @throws SecurityException if there is a <code>SecurityManager</code> that
1079       *         doesn't grant
1080       *         <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
1081       *
1082       * @see #getAWTEventListeners()
1083       * @see #getAWTEventListeners(long)
1084       * @see #removeAWTEventListener(AWTEventListener)
1085       */
1086      public void addAWTEventListener(AWTEventListener listener, long eventMask)
1087      {
1088        // First we must check the security permissions.
1089        SecurityManager s = System.getSecurityManager();
1090        if (s != null)
1091          s.checkPermission(new AWTPermission("listenToAllAWTEvents"));
1092    
1093        // Go through the list and check if the requested listener is already
1094        // registered.
1095        boolean found = false;
1096        for (int i = 0; i < awtEventListeners.length; ++i)
1097          {
1098            AWTEventListenerProxy proxy = awtEventListeners[i];
1099            if (proxy.getListener() == listener)
1100              {
1101                found = true;
1102                // Modify the proxies event mask to include the new event mask.
1103                AWTEventListenerProxy newProxy =
1104                  new AWTEventListenerProxy(proxy.getEventMask() | eventMask,
1105                                            listener);
1106                awtEventListeners[i] = newProxy;
1107                break;
1108              }
1109          }
1110    
1111        // If that listener was not found, then add it.
1112        if (! found)
1113          {
1114            AWTEventListenerProxy proxy =
1115              new AWTEventListenerProxy(eventMask, listener);
1116            AWTEventListenerProxy[] newArray =
1117              new AWTEventListenerProxy[awtEventListeners.length + 1];
1118            System.arraycopy(awtEventListeners, 0, newArray, 0,
1119                             awtEventListeners.length);
1120            newArray[newArray.length - 1] = proxy;
1121            awtEventListeners = newArray;
1122          }
1123      }
1124    
1125      /**
1126       * Removes an AWT event listener from this toolkit. This listener is no
1127       * longer informed of any event types it was registered in.
1128       *
1129       * If a security manager is installed, it is asked first if an
1130       * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
1131       * This may result in a <code>SecurityException</code> beeing thrown.
1132       *
1133       * It is not recommended to use this kind of notification for normal
1134       * applications. It is intended solely for the purpose of debugging and to
1135       * support special facilities.
1136       *
1137       * @param listener the listener to remove
1138       *
1139       * @throws SecurityException if there is a <code>SecurityManager</code> that
1140       *         doesn't grant
1141       *         <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
1142       *
1143       * @since 1.2
1144       *
1145       * @see #addAWTEventListener(AWTEventListener, long)
1146       * @see #getAWTEventListeners()
1147       * @see #getAWTEventListeners(long)
1148       */
1149      public void removeAWTEventListener(AWTEventListener listener)
1150      {
1151        // First we must check the security permissions.
1152        SecurityManager s = System.getSecurityManager();
1153        if (s != null)
1154          s.checkPermission(new AWTPermission("listenToAllAWTEvents"));
1155    
1156    
1157        // Find the index of the listener.
1158        int index = -1;
1159        for (int i = 0; i < awtEventListeners.length; ++i)
1160          {
1161            AWTEventListenerProxy proxy = awtEventListeners[i];
1162            if (proxy.getListener() == listener)
1163              {
1164                index = i;
1165                break;
1166              }
1167          }
1168    
1169        // Copy over the arrays and leave out the removed element.
1170        if (index != -1)
1171          {
1172            AWTEventListenerProxy[] newArray =
1173              new AWTEventListenerProxy[awtEventListeners.length - 1];
1174            if (index > 0)
1175              System.arraycopy(awtEventListeners, 0, newArray, 0, index);
1176            if (index < awtEventListeners.length - 1)
1177              System.arraycopy(awtEventListeners, index + 1, newArray, index,
1178                               awtEventListeners.length - index - 1);
1179            awtEventListeners = newArray;
1180          }
1181      }
1182    
1183      /**
1184       * Returns all registered AWT event listeners. This method returns a copy of
1185       * the listener array, so that application cannot trash the listener list.
1186       *
1187       * If a security manager is installed, it is asked first if an
1188       * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
1189       * This may result in a <code>SecurityException</code> beeing thrown.
1190       *
1191       * It is not recommended to use this kind of notification for normal
1192       * applications. It is intended solely for the purpose of debugging and to
1193       * support special facilities.
1194       *
1195       * @return all registered AWT event listeners
1196       *
1197       * @throws SecurityException if there is a <code>SecurityManager</code> that
1198       *         doesn't grant
1199       *         <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
1200       *
1201       * @since 1.4
1202       *
1203       * @see #addAWTEventListener(AWTEventListener, long)
1204       * @see #removeAWTEventListener(AWTEventListener)
1205       * @see #getAWTEventListeners(long)
1206       */
1207      public AWTEventListener[] getAWTEventListeners()
1208      {
1209        // First we must check the security permissions.
1210        SecurityManager s = System.getSecurityManager();
1211        if (s != null)
1212          s.checkPermission(new AWTPermission("listenToAllAWTEvents"));
1213    
1214        // Create a copy of the array.
1215        AWTEventListener[] copy = new AWTEventListener[awtEventListeners.length];
1216        System.arraycopy(awtEventListeners, 0, copy, 0, awtEventListeners.length);
1217        return copy;
1218      }
1219    
1220      /**
1221       * Returns all registered AWT event listeners that listen for events with
1222       * the specified <code>eventMask</code>. This method returns a copy of
1223       * the listener array, so that application cannot trash the listener list.
1224       *
1225       * If a security manager is installed, it is asked first if an
1226       * <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code> is allowed.
1227       * This may result in a <code>SecurityException</code> beeing thrown.
1228       *
1229       * It is not recommended to use this kind of notification for normal
1230       * applications. It is intended solely for the purpose of debugging and to
1231       * support special facilities.
1232       *
1233       * @param mask the event mask
1234       *
1235       * @throws SecurityException if there is a <code>SecurityManager</code> that
1236       *         doesn't grant
1237       *         <code>AWTPermission(&quot;listenToAllAWTEvents&quot;)</code>
1238       *
1239       *
1240       * @since 1.4
1241       *
1242       * @see #addAWTEventListener(AWTEventListener, long)
1243       * @see #removeAWTEventListener(AWTEventListener)
1244       * @see #getAWTEventListeners()
1245       */
1246      public AWTEventListener[] getAWTEventListeners(long mask)
1247      {
1248        // First we must check the security permissions.
1249        SecurityManager s = System.getSecurityManager();
1250        if (s != null)
1251          s.checkPermission(new AWTPermission("listenToAllAWTEvents"));
1252    
1253        // Create a copy of the array with only the requested listeners in it.
1254        ArrayList l = new ArrayList(awtEventListeners.length);
1255        for (int i = 0; i < awtEventListeners.length; ++i)
1256          {
1257            if ((awtEventListeners[i].getEventMask() & mask) != 0)
1258              l.add(awtEventListeners[i]);
1259          }
1260    
1261        return (AWTEventListener[] ) l.toArray(new AWTEventListener[l.size()]);
1262      }
1263    
1264    
1265      /**
1266       * Dispatches events to listeners registered to this Toolkit. This is called
1267       * by {@link Component#dispatchEventImpl(AWTEvent)} in order to dispatch
1268       * events globally.
1269       *
1270       * @param ev the event to dispatch
1271       */
1272      void globalDispatchEvent(AWTEvent ev)
1273      {
1274        // We do not use the accessor methods here because they create new
1275        // arrays each time. We must be very efficient, so we access this directly.
1276        for (int i = 0; i < awtEventListeners.length; ++i)
1277          {
1278            AWTEventListenerProxy proxy = awtEventListeners[i];
1279            if ((proxy.getEventMask() & AWTEvent.eventIdToMask(ev.getID())) != 0)
1280              proxy.eventDispatched(ev);
1281          }
1282      }
1283    
1284      /**
1285       * @since 1.3
1286       */
1287      public abstract Map<TextAttribute,?>
1288        mapInputMethodHighlight(InputMethodHighlight highlight);
1289    
1290      public abstract boolean isModalExclusionTypeSupported
1291                              (Dialog.ModalExclusionType modalExclusionType);
1292    
1293      public abstract boolean isModalityTypeSupported
1294                              (Dialog.ModalityType modalityType);
1295    
1296      /**
1297       * Initializes the accessibility framework. In particular, this loads the
1298       * properties javax.accessibility.screen_magnifier_present and
1299       * javax.accessibility.screen_reader_present and loads
1300       * the classes specified in javax.accessibility.assistive_technologies.
1301       */
1302      private static void initAccessibility()
1303      {
1304        AccessController.doPrivileged
1305        (new PrivilegedAction()
1306         {
1307           public Object run()
1308           {
1309             Properties props = new Properties();
1310             String sep = File.separator;
1311    
1312             // Try the user configuration.
1313             try
1314               {
1315                 File propsFile = new File(System.getProperty("user.home") + sep
1316                                           + ".accessibility.properties");
1317                 FileInputStream in = new FileInputStream(propsFile);
1318                 props.load(in);
1319                 in.close();
1320               }
1321             catch (Exception ex)
1322               {
1323                 // User configuration not present, ignore.
1324               }
1325    
1326             // Try the system configuration if there was no user configuration.
1327             if (props.size() == 0)
1328               {
1329                 try
1330                   {
1331                     File propsFile =
1332                       new File(System.getProperty("gnu.classpath.home.url")
1333                                + sep + "accessibility.properties");
1334                     FileInputStream in = new FileInputStream(propsFile);
1335                     props.load(in);
1336                     in.close();
1337                   }
1338                 catch (Exception ex)
1339                   {
1340                     // System configuration not present, ignore.
1341                   }
1342               }
1343    
1344           // Fetch the screen_magnifier_present property. Check systen properties
1345           // first, then fallback to the configuration file.
1346           String magPresent = SystemProperties.getProperty
1347                                  ("javax.accessibility.screen_magnifier_present");
1348           if (magPresent == null)
1349             {
1350               magPresent = props.getProperty("screen_magnifier_present");
1351               if (magPresent != null)
1352                 {
1353                   SystemProperties.setProperty
1354                     ("javax.accessibility.screen_magnifier_present", magPresent);
1355                 }
1356             }
1357    
1358           // Fetch the screen_reader_present property. Check systen properties
1359           // first, then fallback to the configuration file.
1360           String readerPresent = SystemProperties.getProperty
1361                                    ("javax.accessibility.screen_reader_present");
1362           if (readerPresent == null)
1363             {
1364               readerPresent = props.getProperty("screen_reader_present");
1365               if (readerPresent != null)
1366                 {
1367                   SystemProperties.setProperty
1368                     ("javax.accessibility.screen_reader_present", readerPresent);
1369                 }
1370             }
1371    
1372           // Fetch the list of classes to be loaded.
1373           String classes = SystemProperties.getProperty
1374             ("javax.accessibility.assistive_technologies");
1375           if (classes == null)
1376             {
1377               classes = props.getProperty("assistive_technologies");
1378               if (classes != null)
1379                 {
1380                   SystemProperties.setProperty
1381                   ("javax.accessibility.assistive_technologies", classes);
1382                 }
1383             }
1384    
1385           // Try to load the assisitive_technologies classes.
1386           if (classes != null)
1387             {
1388               ClassLoader cl = ClassLoader.getSystemClassLoader();
1389               StringTokenizer tokenizer = new StringTokenizer(classes, ",");
1390               while (tokenizer.hasMoreTokens())
1391                 {
1392                   String className = tokenizer.nextToken();
1393                   try
1394                     {
1395                       Class atClass = cl.loadClass(className);
1396                       atClass.newInstance();
1397                     }
1398                   catch (ClassNotFoundException ex)
1399                     {
1400                       AWTError err = new AWTError("Assistive Technology class not"
1401                                                   + " found: " + className);
1402                       err.initCause(ex);
1403                       throw err;
1404                     }
1405                   catch (InstantiationException ex)
1406                     {
1407                       AWTError err =
1408                         new AWTError("Assistive Technology class cannot be "
1409                                      + "instantiated: " + className);
1410                       err.initCause(ex);
1411                       throw err;
1412                     }
1413                   catch (IllegalAccessException ex)
1414                     {
1415                       AWTError err =
1416                         new AWTError("Assistive Technology class cannot be "
1417                                      + "accessed: " + className);
1418                       err.initCause(err);
1419                       throw err;
1420                     }
1421                 }
1422             }
1423           return null;
1424           }
1425         });
1426    
1427      }
1428    
1429    } // class Toolkit