001/* Toolkit.java -- AWT Toolkit superclass
002   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
003   Free Software Foundation, Inc.
004
005This file is part of GNU Classpath.
006
007GNU Classpath is free software; you can redistribute it and/or modify
008it under the terms of the GNU General Public License as published by
009the Free Software Foundation; either version 2, or (at your option)
010any later version.
011
012GNU Classpath is distributed in the hope that it will be useful, but
013WITHOUT ANY WARRANTY; without even the implied warranty of
014MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015General Public License for more details.
016
017You should have received a copy of the GNU General Public License
018along with GNU Classpath; see the file COPYING.  If not, write to the
019Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02002110-1301 USA.
021
022Linking this library statically or dynamically with other modules is
023making a combined work based on this library.  Thus, the terms and
024conditions of the GNU General Public License cover the whole
025combination.
026
027As a special exception, the copyright holders of this library give you
028permission to link this library with independent modules to produce an
029executable, regardless of the license terms of these independent
030modules, and to copy and distribute the resulting executable under
031terms of your choice, provided that you also meet, for each linked
032independent module, the terms and conditions of the license of that
033module.  An independent module is a module which is not derived from
034or based on this library.  If you modify this library, you may extend
035this exception to your version of the library, but you are not
036obligated to do so.  If you do not wish to do so, delete this
037exception statement from your version. */
038
039
040package java.awt;
041
042import gnu.classpath.SystemProperties;
043import gnu.java.awt.AWTUtilities;
044import gnu.java.awt.peer.GLightweightPeer;
045import gnu.java.awt.peer.headless.HeadlessToolkit;
046
047import java.awt.datatransfer.Clipboard;
048import java.awt.dnd.DragGestureEvent;
049import java.awt.dnd.DragGestureListener;
050import java.awt.dnd.DragGestureRecognizer;
051import java.awt.dnd.DragSource;
052import java.awt.dnd.peer.DragSourceContextPeer;
053import java.awt.event.AWTEventListener;
054import java.awt.event.AWTEventListenerProxy;
055import java.awt.event.KeyEvent;
056import java.awt.font.TextAttribute;
057import java.awt.im.InputMethodHighlight;
058import java.awt.image.ColorModel;
059import java.awt.image.ImageObserver;
060import java.awt.image.ImageProducer;
061import java.awt.peer.ButtonPeer;
062import java.awt.peer.CanvasPeer;
063import java.awt.peer.CheckboxMenuItemPeer;
064import java.awt.peer.CheckboxPeer;
065import java.awt.peer.ChoicePeer;
066import java.awt.peer.DesktopPeer;
067import java.awt.peer.DialogPeer;
068import java.awt.peer.FileDialogPeer;
069import java.awt.peer.FontPeer;
070import java.awt.peer.FramePeer;
071import java.awt.peer.LabelPeer;
072import java.awt.peer.LightweightPeer;
073import java.awt.peer.ListPeer;
074import java.awt.peer.MenuBarPeer;
075import java.awt.peer.MenuItemPeer;
076import java.awt.peer.MenuPeer;
077import java.awt.peer.MouseInfoPeer;
078import java.awt.peer.PanelPeer;
079import java.awt.peer.PopupMenuPeer;
080import java.awt.peer.ScrollPanePeer;
081import java.awt.peer.ScrollbarPeer;
082import java.awt.peer.TextAreaPeer;
083import java.awt.peer.TextFieldPeer;
084import java.awt.peer.WindowPeer;
085import java.beans.PropertyChangeListener;
086import java.beans.PropertyChangeSupport;
087import java.io.File;
088import java.io.FileInputStream;
089import java.net.URL;
090import java.security.AccessController;
091import java.security.PrivilegedAction;
092import java.util.ArrayList;
093import java.util.Hashtable;
094import java.util.Map;
095import java.util.Properties;
096import 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 */
112public 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