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 “System” 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 “System” 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("listenToAllAWTEvents")</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("listenToAllAWTEvents")</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("listenToAllAWTEvents")</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("listenToAllAWTEvents")</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("listenToAllAWTEvents")</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("listenToAllAWTEvents")</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("listenToAllAWTEvents")</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("listenToAllAWTEvents")</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