1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.awt;
19
20import java.awt.event.AWTEventListener;
21import java.awt.event.AWTEventListenerProxy;
22import java.awt.event.InputEvent;
23import java.awt.im.InputMethodHighlight;
24import java.awt.image.ColorModel;
25import java.awt.image.ImageObserver;
26import java.awt.image.ImageProducer;
27import java.awt.peer.FontPeer;
28import java.beans.PropertyChangeListener;
29import java.beans.PropertyChangeSupport;
30
31import java.lang.reflect.InvocationTargetException;
32import java.net.URL;
33import java.security.AccessController;
34import java.security.PrivilegedAction;
35import java.util.Collections;
36import java.util.EventListener;
37import java.util.HashMap;
38import java.util.HashSet;
39import java.util.Iterator;
40import java.util.Map;
41import java.util.MissingResourceException;
42import java.util.Properties;
43import java.util.ResourceBundle;
44
45import org.apache.harmony.awt.ChoiceStyle;
46import org.apache.harmony.awt.ComponentInternals;
47import org.apache.harmony.awt.ContextStorage;
48import org.apache.harmony.awt.ReadOnlyIterator;
49import org.apache.harmony.awt.internal.nls.Messages;
50import org.apache.harmony.awt.wtk.CreationParams;
51import org.apache.harmony.awt.wtk.GraphicsFactory;
52import org.apache.harmony.awt.wtk.NativeCursor;
53
54import org.apache.harmony.awt.wtk.NativeEventQueue;
55import org.apache.harmony.awt.wtk.NativeEventThread;
56import org.apache.harmony.awt.wtk.ShutdownWatchdog;
57import org.apache.harmony.awt.wtk.Synchronizer;
58import org.apache.harmony.awt.wtk.WTK;
59import org.apache.harmony.luni.util.NotImplementedException;
60
61/**
62 * The Toolkit class is the representation of the platform-specific Abstract
63 * Window Toolkit implementation. Toolkit's subclasses are used to bind the
64 * various components to particular native toolkit implementations.
65 *
66 * @since Android 1.0
67 */
68public abstract class Toolkit {
69
70    /**
71     * The Constant RECOURCE_PATH.
72     */
73    private static final String RECOURCE_PATH = "org.apache.harmony.awt.resources.AWTProperties"; //$NON-NLS-1$
74
75    /**
76     * The Constant properties.
77     */
78    private static final ResourceBundle properties = loadResources(RECOURCE_PATH);
79
80    /**
81     * The dispatcher.
82     */
83    Dispatcher dispatcher;
84
85    /**
86     * The system event queue core.
87     */
88    private EventQueueCore systemEventQueueCore;
89
90    /**
91     * The dispatch thread.
92     */
93    EventDispatchThread dispatchThread;
94
95    /**
96     * The native thread.
97     */
98    NativeEventThread nativeThread;
99
100    /**
101     * The AWT events manager.
102     */
103    protected AWTEventsManager awtEventsManager;
104
105    /**
106     * The Class AWTTreeLock.
107     */
108    private class AWTTreeLock {
109    }
110
111    /**
112     * The AWT tree lock.
113     */
114    final Object awtTreeLock = new AWTTreeLock();
115
116    /**
117     * The synchronizer.
118     */
119    private final Synchronizer synchronizer = ContextStorage.getSynchronizer();
120
121    /**
122     * The shutdown watchdog.
123     */
124    final ShutdownWatchdog shutdownWatchdog = new ShutdownWatchdog();
125
126    /**
127     * The auto number.
128     */
129    final AutoNumber autoNumber = new AutoNumber();
130
131    /**
132     * The event type lookup.
133     */
134    final AWTEvent.EventTypeLookup eventTypeLookup = new AWTEvent.EventTypeLookup();
135
136    /**
137     * The b dynamic layout set.
138     */
139    private boolean bDynamicLayoutSet = true;
140
141    /**
142     * The set of desktop properties that user set directly.
143     */
144    private final HashSet<String> userPropSet = new HashSet<String>();
145
146    /**
147     * The desktop properties.
148     */
149    protected Map<String, Object> desktopProperties;
150
151    /**
152     * The desktop props support.
153     */
154    protected PropertyChangeSupport desktopPropsSupport;
155
156    /**
157     * For this component the native window is being created It is used in the
158     * callback-driven window creation (e.g. on Windows in the handler of
159     * WM_CREATE event) to establish the connection between this component and
160     * its native window.
161     */
162    private Object recentNativeWindowComponent;
163
164    /**
165     * The wtk.
166     */
167    private WTK wtk;
168
169    /**
170     * The Class ComponentInternalsImpl.
171     *
172     * @since Android 1.0
173     */
174    protected final class ComponentInternalsImpl extends ComponentInternals {
175
176        /**
177         * Shutdown.
178         */
179        @Override
180        public void shutdown() {
181            dispatchThread.shutdown();
182        }
183
184        /**
185         * Sets the desktop property to the specified value and fires a property
186         * change event.
187         *
188         * @param name
189         *            the name of property.
190         * @param value
191         *            the new value of property.
192         */
193        @Override
194        public void setDesktopProperty(String name, Object value) {
195            Toolkit.this.setDesktopProperty(name, value);
196        }
197    }
198
199    /**
200     * A lot of methods must throw HeadlessException if
201     * <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>.
202     *
203     * @throws HeadlessException
204     *             the headless exception.
205     */
206    static void checkHeadless() throws HeadlessException {
207        if (GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance())
208            throw new HeadlessException();
209    }
210
211    /**
212     * Lock AWT.
213     */
214    final void lockAWT() {
215        synchronizer.lock();
216    }
217
218    /**
219     * Static lock AWT.
220     */
221    static final void staticLockAWT() {
222        ContextStorage.getSynchronizer().lock();
223    }
224
225    /**
226     * Unlock AWT.
227     */
228    final void unlockAWT() {
229        synchronizer.unlock();
230    }
231
232    /**
233     * Static unlock AWT.
234     */
235    static final void staticUnlockAWT() {
236        ContextStorage.getSynchronizer().unlock();
237    }
238
239    /**
240     * InvokeAndWait under AWT lock. W/o this method system can hang up. Added
241     * to support modality (Dialog.show() & PopupMenu.show()) from not event
242     * dispatch thread. Use in other cases is not recommended. Still can be
243     * called only for whole API methods that cannot be called from other
244     * classes API methods. Examples: show() for modal dialogs - correct, only
245     * user can call it, directly or through setVisible(true) setBounds() for
246     * components - incorrect, setBounds() can be called from layoutContainer()
247     * for layout managers
248     *
249     * @param runnable
250     *            the runnable.
251     * @throws InterruptedException
252     *             the interrupted exception.
253     * @throws InvocationTargetException
254     *             the invocation target exception.
255     */
256    final void unsafeInvokeAndWait(Runnable runnable) throws InterruptedException,
257            InvocationTargetException {
258        synchronizer.storeStateAndFree();
259        try {
260            EventQueue.invokeAndWait(runnable);
261        } finally {
262            synchronizer.lockAndRestoreState();
263        }
264    }
265
266    /**
267     * Gets the synchronizer.
268     *
269     * @return the synchronizer.
270     */
271    final Synchronizer getSynchronizer() {
272        return synchronizer;
273    }
274
275    /**
276     * Gets the wTK.
277     *
278     * @return the wTK.
279     */
280    final WTK getWTK() {
281        return wtk;
282    }
283
284    /**
285     * Gets the property with the specified key and default value. This method
286     * returns the defValue if the property is not found.
287     *
288     * @param propName
289     *            the name of property.
290     * @param defVal
291     *            the default value.
292     * @return the property value.
293     */
294    public static String getProperty(String propName, String defVal) {
295        if (propName == null) {
296            // awt.7D=Property name is null
297            throw new NullPointerException(Messages.getString("awt.7D")); //$NON-NLS-1$
298        }
299        staticLockAWT();
300        try {
301            String retVal = null;
302            if (properties != null) {
303                try {
304                    retVal = properties.getString(propName);
305                } catch (MissingResourceException e) {
306                } catch (ClassCastException e) {
307                }
308            }
309            return (retVal == null) ? defVal : retVal;
310        } finally {
311            staticUnlockAWT();
312        }
313    }
314
315    /**
316     * Gets the default Toolkit.
317     *
318     * @return the default Toolkit.
319     */
320    public static Toolkit getDefaultToolkit() {
321        synchronized (ContextStorage.getContextLock()) {
322            if (ContextStorage.shutdownPending()) {
323                return null;
324            }
325            Toolkit defToolkit = ContextStorage.getDefaultToolkit();
326            if (defToolkit != null) {
327                return defToolkit;
328            }
329            staticLockAWT();
330            try {
331                defToolkit = GraphicsEnvironment.isHeadless() ? new HeadlessToolkit()
332                        : new ToolkitImpl();
333                ContextStorage.setDefaultToolkit(defToolkit);
334                return defToolkit;
335            } finally {
336                staticUnlockAWT();
337            }
338            // TODO: read system property named awt.toolkit
339            // and create an instance of the specified class,
340            // by default use ToolkitImpl
341        }
342    }
343
344    /**
345     * Gets the default Font.
346     *
347     * @return the default Font for Toolkit.
348     */
349    Font getDefaultFont() {
350        return wtk.getSystemProperties().getDefaultFont();
351    }
352
353    /**
354     * Load resources.
355     *
356     * @param path
357     *            the path.
358     * @return the resource bundle.
359     */
360    private static ResourceBundle loadResources(String path) {
361        try {
362            return ResourceBundle.getBundle(path);
363        } catch (MissingResourceException e) {
364            return null;
365        }
366    }
367
368    /**
369     * Gets the wTK class name.
370     *
371     * @return the wTK class name.
372     */
373    private static String getWTKClassName() {
374        return "com.android.internal.awt.AndroidWTK";
375    }
376
377    /**
378     * Gets the component by id.
379     *
380     * @param id
381     *            the id.
382     * @return the component by id.
383     */
384    Component getComponentById(long id) {
385        if (id == 0) {
386            return null;
387        }
388        return null;
389    }
390
391    /**
392     * Gets the GraphicsFactory.
393     *
394     * @return the GraphicsFactory object.
395     */
396    public GraphicsFactory getGraphicsFactory() {
397        return wtk.getGraphicsFactory();
398    }
399
400    /**
401     * Instantiates a new toolkit.
402     */
403    public Toolkit() {
404        init();
405    }
406
407    /**
408     * Initiates AWT.
409     */
410    protected void init() {
411        lockAWT();
412        try {
413            ComponentInternals.setComponentInternals(new ComponentInternalsImpl());
414            new EventQueue(this); // create the system EventQueue
415            dispatcher = new Dispatcher(this);
416            final String className = getWTKClassName();
417            desktopProperties = new HashMap<String, Object>();
418            desktopPropsSupport = new PropertyChangeSupport(this);
419            awtEventsManager = new AWTEventsManager();
420            dispatchThread = new EventDispatchThread(this, dispatcher);
421            nativeThread = new NativeEventThread();
422            NativeEventThread.Init init = new NativeEventThread.Init() {
423                public WTK init() {
424                    wtk = createWTK(className);
425                    wtk.getNativeEventQueue().setShutdownWatchdog(shutdownWatchdog);
426                    synchronizer.setEnvironment(wtk, dispatchThread);
427                    ContextStorage.setWTK(wtk);
428                    return wtk;
429                }
430            };
431            nativeThread.start(init);
432            dispatchThread.start();
433            wtk.getNativeEventQueue().awake();
434        } finally {
435            unlockAWT();
436        }
437    }
438
439    /**
440     * Synchronizes this toolkit's graphics.
441     */
442    public abstract void sync();
443
444    /**
445     * Returns the construction status of a specified image that is being
446     * created.
447     *
448     * @param a0
449     *            the image to be checked.
450     * @param a1
451     *            the width of scaled image for which the status is being
452     *            checked or -1.
453     * @param a2
454     *            the height of scaled image for which the status is being
455     *            checked or -1.
456     * @param a3
457     *            the ImageObserver object to be notified while the image is
458     *            being prepared.
459     * @return the ImageObserver flags which give the current state of the image
460     *         data.
461     */
462    public abstract int checkImage(Image a0, int a1, int a2, ImageObserver a3);
463
464    /**
465     * Creates the image with the specified ImageProducer.
466     *
467     * @param a0
468     *            the ImageProducer to be used for image creation.
469     * @return the image with the specified ImageProducer.
470     */
471    public abstract Image createImage(ImageProducer a0);
472
473    /**
474     * Creates the image from the specified byte array, offset and length. The
475     * byte array should contain data with image format supported by Toolkit
476     * such as JPEG, GIF, or PNG.
477     *
478     * @param a0
479     *            the byte array with the image data.
480     * @param a1
481     *            the offset of the beginning the image data in the byte array.
482     * @param a2
483     *            the length of the image data in the byte array.
484     * @return the created Image.
485     */
486    public abstract Image createImage(byte[] a0, int a1, int a2);
487
488    /**
489     * Creates the image using image data from the specified URL.
490     *
491     * @param a0
492     *            the URL for extracting image data.
493     * @return the Image.
494     */
495    public abstract Image createImage(URL a0);
496
497    /**
498     * Creates the image using image data from the specified file.
499     *
500     * @param a0
501     *            the file name which contains image data of supported format.
502     * @return the Image.
503     */
504    public abstract Image createImage(String a0);
505
506    /**
507     * Gets the color model.
508     *
509     * @return the ColorModel of Toolkit's screen.
510     * @throws HeadlessException
511     *             if the GraphicsEnvironment.isHeadless() method returns true.
512     */
513    public abstract ColorModel getColorModel() throws HeadlessException;
514
515    /**
516     * Gets the screen device metrics for the specified font.
517     *
518     * @param font
519     *            the Font.
520     * @return the FontMetrics for the specified Font.
521     * @deprecated Use getLineMetrics method from Font class.
522     */
523
524    @Deprecated
525    public abstract FontMetrics getFontMetrics(Font font);
526
527    /**
528     * Prepares the specified image for rendering on the screen with the
529     * specified size.
530     *
531     * @param a0
532     *            the Image to be prepared.
533     * @param a1
534     *            the width of the screen representation or -1 for the current
535     *            screen.
536     * @param a2
537     *            the height of the screen representation or -1 for the current
538     *            screen.
539     * @param a3
540     *            the ImageObserver object to be notified as soon as the image
541     *            is prepared.
542     * @return true, if image is fully prepared, false otherwise.
543     */
544    public abstract boolean prepareImage(Image a0, int a1, int a2, ImageObserver a3);
545
546    /**
547     * Creates an audio beep.
548     */
549    public abstract void beep();
550
551    /**
552     * Returns the array of font names which are available in this Toolkit.
553     *
554     * @return the array of font names which are available in this Toolkit.
555     * @deprecated use GraphicsEnvironment.getAvailableFontFamilyNames() method.
556     */
557    @Deprecated
558    public abstract String[] getFontList();
559
560    /**
561     * Gets the the Font implementation using the specified peer interface.
562     *
563     * @param a0
564     *            the Font name to be implemented.
565     * @param a1
566     *            the the font style: PLAIN, BOLD, ITALIC.
567     * @return the FontPeer implementation of the specified Font.
568     * @deprecated use java.awt.GraphicsEnvironment.getAllFonts method.
569     */
570
571    @Deprecated
572    protected abstract FontPeer getFontPeer(String a0, int a1);
573
574    /**
575     * Gets the image from the specified file which contains image data in a
576     * supported image format (such as JPEG, GIF, or PNG); this method should
577     * return the same Image for multiple calls of this method with the same
578     * image file name.
579     *
580     * @param a0
581     *            the file name which contains image data in a supported image
582     *            format (such as JPEG, GIF, or PNG).
583     * @return the Image.
584     */
585    public abstract Image getImage(String a0);
586
587    /**
588     * Gets the image from the specified URL which contains image data in a
589     * supported image format (such as JPEG, GIF, or PNG); this method should
590     * return the same Image for multiple calls of this method with the same
591     * image URL.
592     *
593     * @param a0
594     *            the URL which contains image data in a supported image format
595     *            (such as JPEG, GIF, or PNG).
596     * @return the Image.
597     */
598    public abstract Image getImage(URL a0);
599
600    /**
601     * Gets the screen resolution.
602     *
603     * @return the screen resolution.
604     * @throws HeadlessException
605     *             if the GraphicsEnvironment.isHeadless() method returns true.
606     */
607    public abstract int getScreenResolution() throws HeadlessException;
608
609    /**
610     * Gets the screen size.
611     *
612     * @return a Dimension object containing the width and height of the screen.
613     * @throws HeadlessException
614     *             if the GraphicsEnvironment.isHeadless() method returns true.
615     */
616    public abstract Dimension getScreenSize() throws HeadlessException;
617
618    /**
619     * Gets the EventQueue instance without checking access.
620     *
621     * @return the system EventQueue.
622     */
623    protected abstract EventQueue getSystemEventQueueImpl();
624
625    /**
626     * Returns a map of text attributes for the abstract level description of
627     * the specified input method highlight, or null if no mapping is found.
628     *
629     * @param highlight
630     *            the InputMethodHighlight.
631     * @return the Map<java.awt.font. text attribute,?>.
632     * @throws HeadlessException
633     *             if the GraphicsEnvironment.isHeadless() method returns true.
634     */
635    public abstract Map<java.awt.font.TextAttribute, ?> mapInputMethodHighlight(
636            InputMethodHighlight highlight) throws HeadlessException;
637
638    /**
639     * Map input method highlight impl.
640     *
641     * @param highlight
642     *            the highlight.
643     * @return the map<java.awt.font. text attribute,?>.
644     * @throws HeadlessException
645     *             the headless exception.
646     */
647    Map<java.awt.font.TextAttribute, ?> mapInputMethodHighlightImpl(InputMethodHighlight highlight)
648            throws HeadlessException {
649        HashMap<java.awt.font.TextAttribute, ?> map = new HashMap<java.awt.font.TextAttribute, Object>();
650        wtk.getSystemProperties().mapInputMethodHighlight(highlight, map);
651        return Collections.<java.awt.font.TextAttribute, Object> unmodifiableMap(map);
652    }
653
654    /**
655     * Adds the specified PropertyChangeListener listener for the specified
656     * property.
657     *
658     * @param propName
659     *            the property name for which the specified
660     *            PropertyChangeListener will be added.
661     * @param l
662     *            the PropertyChangeListener object.
663     */
664    public void addPropertyChangeListener(String propName, PropertyChangeListener l) {
665        lockAWT();
666        try {
667            if (desktopProperties.isEmpty()) {
668                initializeDesktopProperties();
669            }
670        } finally {
671            unlockAWT();
672        }
673        if (l != null) { // there is no guarantee that null listener will not be
674            // added
675            desktopPropsSupport.addPropertyChangeListener(propName, l);
676        }
677    }
678
679    /**
680     * Returns an array of the property change listeners registered with this
681     * Toolkit.
682     *
683     * @return an array of the property change listeners registered with this
684     *         Toolkit.
685     */
686    public PropertyChangeListener[] getPropertyChangeListeners() {
687        return desktopPropsSupport.getPropertyChangeListeners();
688    }
689
690    /**
691     * Returns an array of the property change listeners registered with this
692     * Toolkit for notification regarding the specified property.
693     *
694     * @param propName
695     *            the property name for which the PropertyChangeListener was
696     *            registered.
697     * @return the array of PropertyChangeListeners registered for the specified
698     *         property name.
699     */
700    public PropertyChangeListener[] getPropertyChangeListeners(String propName) {
701        return desktopPropsSupport.getPropertyChangeListeners(propName);
702    }
703
704    /**
705     * Removes the specified property change listener registered for the
706     * specified property name.
707     *
708     * @param propName
709     *            the property name.
710     * @param l
711     *            the PropertyChangeListener registered for the specified
712     *            property name.
713     */
714    public void removePropertyChangeListener(String propName, PropertyChangeListener l) {
715        desktopPropsSupport.removePropertyChangeListener(propName, l);
716    }
717
718    /**
719     * Creates a custom cursor with the specified Image, hot spot, and cursor
720     * description.
721     *
722     * @param img
723     *            the image of activated cursor.
724     * @param hotSpot
725     *            the Point giving the coordinates of the cursor's hot spot.
726     * @param name
727     *            the cursor description.
728     * @return the cursor with the specified Image, hot spot, and cursor
729     *         description.
730     * @throws IndexOutOfBoundsException
731     *             if the hot spot values are outside the bounds of the cursor.
732     * @throws HeadlessException
733     *             if isHeadless() method of GraphicsEnvironment class returns
734     *             true.
735     */
736    public Cursor createCustomCursor(Image img, Point hotSpot, String name)
737            throws IndexOutOfBoundsException, HeadlessException {
738        lockAWT();
739        try {
740            int w = img.getWidth(null), x = hotSpot.x;
741            int h = img.getHeight(null), y = hotSpot.y;
742            if (x < 0 || x >= w || y < 0 || y >= h) {
743                // awt.7E=invalid hotSpot
744                throw new IndexOutOfBoundsException(Messages.getString("awt.7E")); //$NON-NLS-1$
745            }
746            return new Cursor(name, img, hotSpot);
747        } finally {
748            unlockAWT();
749        }
750    }
751
752    /**
753     * Returns the supported cursor dimension which is closest to the specified
754     * width and height. If the Toolkit only supports a single cursor size, this
755     * method should return the supported cursor size. If custom cursor is not
756     * supported, a dimension of 0, 0 should be returned.
757     *
758     * @param prefWidth
759     *            the preferred cursor width.
760     * @param prefHeight
761     *            the preferred cursor height.
762     * @return the supported cursor dimension which is closest to the specified
763     *         width and height.
764     * @throws HeadlessException
765     *             if GraphicsEnvironment.isHeadless() returns true.
766     */
767    public Dimension getBestCursorSize(int prefWidth, int prefHeight) throws HeadlessException {
768        lockAWT();
769        try {
770            return wtk.getCursorFactory().getBestCursorSize(prefWidth, prefHeight);
771        } finally {
772            unlockAWT();
773        }
774    }
775
776    /**
777     * Gets the value for the specified desktop property.
778     *
779     * @param propName
780     *            the property name.
781     * @return the Object that is the property's value.
782     */
783    public final Object getDesktopProperty(String propName) {
784        lockAWT();
785        try {
786            if (desktopProperties.isEmpty()) {
787                initializeDesktopProperties();
788            }
789            if (propName.equals("awt.dynamicLayoutSupported")) { //$NON-NLS-1$
790                // dynamicLayoutSupported is special case
791                return Boolean.valueOf(isDynamicLayoutActive());
792            }
793            Object val = desktopProperties.get(propName);
794            if (val == null) {
795                // try to lazily load prop value
796                // just for compatibility, our lazilyLoad is empty
797                val = lazilyLoadDesktopProperty(propName);
798            }
799            return val;
800        } finally {
801            unlockAWT();
802        }
803    }
804
805    /**
806     * Returns the locking key state for the specified key.
807     *
808     * @param a0
809     *            the key code: VK_CAPS_LOCK, VK_NUM_LOCK, VK_SCROLL_LOCK, or
810     *            VK_KANA_LOCK.
811     * @return true if the specified key code is in the locked state, false
812     *         otherwise.
813     * @throws UnsupportedOperationException
814     *             if the state of this key can't be retrieved, or if the
815     *             keyboard doesn't have this key.
816     * @throws NotImplementedException
817     *             if this method is not implemented.
818     */
819    public boolean getLockingKeyState(int a0) throws UnsupportedOperationException,
820            org.apache.harmony.luni.util.NotImplementedException {
821        lockAWT();
822        try {
823        } finally {
824            unlockAWT();
825        }
826        if (true) {
827            throw new RuntimeException("Method is not implemented"); //TODO: implement //$NON-NLS-1$
828        }
829        return true;
830    }
831
832    /**
833     * Returns the maximum number of colors which the Toolkit supports for
834     * custom cursor.
835     *
836     * @return the maximum cursor colors.
837     * @throws HeadlessException
838     *             if the GraphicsEnvironment.isHeadless() method returns true.
839     */
840    public int getMaximumCursorColors() throws HeadlessException {
841        lockAWT();
842        try {
843            return wtk.getCursorFactory().getMaximumCursorColors();
844        } finally {
845            unlockAWT();
846        }
847    }
848
849    /**
850     * Gets the menu shortcut key mask.
851     *
852     * @return the menu shortcut key mask.
853     * @throws HeadlessException
854     *             if the GraphicsEnvironment.isHeadless() method returns true.
855     */
856    public int getMenuShortcutKeyMask() throws HeadlessException {
857        lockAWT();
858        try {
859            return InputEvent.CTRL_MASK;
860        } finally {
861            unlockAWT();
862        }
863    }
864
865    /**
866     * Gets the screen insets.
867     *
868     * @param gc
869     *            the GraphicsConfiguration.
870     * @return the insets of this toolkit.
871     * @throws HeadlessException
872     *             if the GraphicsEnvironment.isHeadless() method returns true.
873     */
874    public Insets getScreenInsets(GraphicsConfiguration gc) throws HeadlessException {
875        if (gc == null) {
876            throw new NullPointerException();
877        }
878        lockAWT();
879        try {
880            return new Insets(0, 0, 0, 0); // TODO: get real screen insets
881        } finally {
882            unlockAWT();
883        }
884    }
885
886    /**
887     * Gets the system EventQueue instance. If the default implementation of
888     * checkAwtEventQueueAccess is used, then this results of a call to the
889     * security manager's checkPermission method with an
890     * AWTPermission("accessEventQueue") permission.
891     *
892     * @return the system EventQueue instance.
893     */
894    public final EventQueue getSystemEventQueue() {
895        SecurityManager sm = System.getSecurityManager();
896        if (sm != null) {
897            sm.checkAwtEventQueueAccess();
898        }
899        return getSystemEventQueueImpl();
900    }
901
902    /**
903     * Gets the system event queue core.
904     *
905     * @return the system event queue core.
906     */
907    EventQueueCore getSystemEventQueueCore() {
908        return systemEventQueueCore;
909    }
910
911    /**
912     * Sets the system event queue core.
913     *
914     * @param core
915     *            the new system event queue core.
916     */
917    void setSystemEventQueueCore(EventQueueCore core) {
918        systemEventQueueCore = core;
919    }
920
921    /**
922     * Initialize the desktop properties.
923     */
924    protected void initializeDesktopProperties() {
925        lockAWT();
926        try {
927            wtk.getSystemProperties().init(desktopProperties);
928        } finally {
929            unlockAWT();
930        }
931    }
932
933    /**
934     * Checks if dynamic layout of Containers is active or not.
935     *
936     * @return true, if is dynamic layout of Containers is active, false
937     *         otherwise.
938     * @throws HeadlessException
939     *             if the GraphicsEnvironment.isHeadless() method returns true.
940     */
941    public boolean isDynamicLayoutActive() throws HeadlessException {
942        lockAWT();
943        try {
944            // always return true
945            return true;
946        } finally {
947            unlockAWT();
948        }
949    }
950
951    /**
952     * Returns if the layout of Containers is checked dynamically during
953     * resizing, or statically after resizing is completed.
954     *
955     * @return true, if if the layout of Containers is checked dynamically
956     *         during resizing; false, if the layout of Containers is checked
957     *         statically after resizing is completed.
958     * @throws HeadlessException
959     *             if the GraphicsEnvironment.isHeadless() method returns true.
960     */
961    protected boolean isDynamicLayoutSet() throws HeadlessException {
962        lockAWT();
963        try {
964            return bDynamicLayoutSet;
965        } finally {
966            unlockAWT();
967        }
968    }
969
970    /**
971     * Checks if the specified frame state is supported by Toolkit or not.
972     *
973     * @param state
974     *            the frame state.
975     * @return true, if frame state is supported, false otherwise.
976     * @throws HeadlessException
977     *             if the GraphicsEnvironment.isHeadless() method returns true.
978     */
979    public boolean isFrameStateSupported(int state) throws HeadlessException {
980        lockAWT();
981        try {
982            return wtk.getWindowFactory().isWindowStateSupported(state);
983        } finally {
984            unlockAWT();
985        }
986    }
987
988    /**
989     * Loads the value of the desktop property with the specified property name.
990     *
991     * @param propName
992     *            the property name.
993     * @return the desktop property values.
994     */
995    protected Object lazilyLoadDesktopProperty(String propName) {
996        return null;
997    }
998
999    /**
1000     * Loads the current system color values to the specified array.
1001     *
1002     * @param colors
1003     *            the array where the current system color values are written by
1004     *            this method.
1005     * @throws HeadlessException
1006     *             if the GraphicsEnvironment.isHeadless() method returns true.
1007     */
1008    protected void loadSystemColors(int[] colors) throws HeadlessException {
1009        lockAWT();
1010        try {
1011        } finally {
1012            unlockAWT();
1013        }
1014    }
1015
1016    /**
1017     * Sets the value of the desktop property with the specified name.
1018     *
1019     * @param propName
1020     *            the property's name.
1021     * @param value
1022     *            the property's value.
1023     */
1024    protected final void setDesktopProperty(String propName, Object value) {
1025        Object oldVal;
1026        lockAWT();
1027        try {
1028            oldVal = getDesktopProperty(propName);
1029            userPropSet.add(propName);
1030            desktopProperties.put(propName, value);
1031        } finally {
1032            unlockAWT();
1033        }
1034        desktopPropsSupport.firePropertyChange(propName, oldVal, value);
1035    }
1036
1037    /**
1038     * Sets the layout state, whether the Container layout is checked
1039     * dynamically during resizing, or statically after resizing is completed.
1040     *
1041     * @param dynamic
1042     *            the new dynamic layout state - if true the layout of
1043     *            Containers is checked dynamically during resizing, if false -
1044     *            statically after resizing is completed.
1045     * @throws HeadlessException
1046     *             if the GraphicsEnvironment.isHeadless() method returns true.
1047     */
1048    public void setDynamicLayout(boolean dynamic) throws HeadlessException {
1049        lockAWT();
1050        try {
1051            bDynamicLayoutSet = dynamic;
1052        } finally {
1053            unlockAWT();
1054        }
1055    }
1056
1057    /**
1058     * Sets the locking key state for the specified key code.
1059     *
1060     * @param a0
1061     *            the key code: VK_CAPS_LOCK, VK_NUM_LOCK, VK_SCROLL_LOCK, or
1062     *            VK_KANA_LOCK.
1063     * @param a1
1064     *            the state - true to set the specified key code to the locked
1065     *            state, false - to unlock it.
1066     * @throws UnsupportedOperationException
1067     *             if the state of this key can't be set, or if the keyboard
1068     *             doesn't have this key.
1069     * @throws NotImplementedException
1070     *             if this method is not implemented.
1071     */
1072    public void setLockingKeyState(int a0, boolean a1) throws UnsupportedOperationException,
1073            org.apache.harmony.luni.util.NotImplementedException {
1074        lockAWT();
1075        try {
1076        } finally {
1077            unlockAWT();
1078        }
1079        if (true) {
1080            throw new RuntimeException("Method is not implemented"); //TODO: implement //$NON-NLS-1$
1081        }
1082        return;
1083    }
1084
1085    /**
1086     * On queue empty.
1087     */
1088    void onQueueEmpty() {
1089        throw new RuntimeException("Not implemented!");
1090    }
1091
1092    /**
1093     * Creates the wtk.
1094     *
1095     * @param clsName
1096     *            the cls name.
1097     * @return the wTK.
1098     */
1099    private WTK createWTK(String clsName) {
1100        WTK newWTK = null;
1101        try {
1102            newWTK = (WTK)Class.forName(clsName).newInstance();
1103        } catch (Exception e) {
1104            throw new RuntimeException(e);
1105        }
1106        return newWTK;
1107    }
1108
1109    /**
1110     * Connect the component to its native window
1111     *
1112     * @param winId
1113     *            the id of native window just created.
1114     */
1115    boolean onWindowCreated(long winId) {
1116        return false;
1117    }
1118
1119    /**
1120     * Gets the native event queue.
1121     *
1122     * @return the native event queue.
1123     */
1124    NativeEventQueue getNativeEventQueue() {
1125        return wtk.getNativeEventQueue();
1126    }
1127
1128    /**
1129     * Returns a shared instance of implementation of
1130     * org.apache.harmony.awt.wtk.NativeCursor for current platform for.
1131     *
1132     * @param type
1133     *            the Java Cursor type.
1134     * @return new instance of implementation of NativeCursor.
1135     */
1136    NativeCursor createNativeCursor(int type) {
1137        return wtk.getCursorFactory().getCursor(type);
1138    }
1139
1140    /**
1141     * Returns a shared instance of implementation of
1142     * org.apache.harmony.awt.wtk.NativeCursor for current platform for custom
1143     * cursor
1144     *
1145     * @param img
1146     *            the img.
1147     * @param hotSpot
1148     *            the hot spot.
1149     * @param name
1150     *            the name.
1151     * @return new instance of implementation of NativeCursor.
1152     */
1153    NativeCursor createCustomNativeCursor(Image img, Point hotSpot, String name) {
1154        return wtk.getCursorFactory().createCustomCursor(img, hotSpot.x, hotSpot.y);
1155    }
1156
1157    /**
1158     * Adds an AWTEventListener to the Toolkit to listen for events of types
1159     * corresponding to bits in the specified event mask. Event masks are
1160     * defined in AWTEvent class.
1161     *
1162     * @param listener
1163     *            the AWTEventListener.
1164     * @param eventMask
1165     *            the bitmask of event types.
1166     */
1167    public void addAWTEventListener(AWTEventListener listener, long eventMask) {
1168        lockAWT();
1169        try {
1170            SecurityManager security = System.getSecurityManager();
1171            if (security != null) {
1172                security.checkPermission(awtEventsManager.permission);
1173            }
1174            awtEventsManager.addAWTEventListener(listener, eventMask);
1175        } finally {
1176            unlockAWT();
1177        }
1178    }
1179
1180    /**
1181     * Removes the specified AWT event listener.
1182     *
1183     * @param listener
1184     *            the AWTEventListener to be removed.
1185     */
1186    public void removeAWTEventListener(AWTEventListener listener) {
1187        lockAWT();
1188        try {
1189            SecurityManager security = System.getSecurityManager();
1190            if (security != null) {
1191                security.checkPermission(awtEventsManager.permission);
1192            }
1193            awtEventsManager.removeAWTEventListener(listener);
1194        } finally {
1195            unlockAWT();
1196        }
1197    }
1198
1199    /**
1200     * Gets the array of all AWT event listeners registered with this Toolkit.
1201     *
1202     * @return the array of all AWT event listeners registered with this
1203     *         Toolkit.
1204     */
1205    public AWTEventListener[] getAWTEventListeners() {
1206        lockAWT();
1207        try {
1208            SecurityManager security = System.getSecurityManager();
1209            if (security != null) {
1210                security.checkPermission(awtEventsManager.permission);
1211            }
1212            return awtEventsManager.getAWTEventListeners();
1213        } finally {
1214            unlockAWT();
1215        }
1216    }
1217
1218    /**
1219     * Returns the array of the AWT event listeners registered with this Toolkit
1220     * for the event types corresponding to the specified event mask.
1221     *
1222     * @param eventMask
1223     *            the bit mask of event type.
1224     * @return the array of the AWT event listeners registered in this Toolkit
1225     *         for the event types corresponding to the specified event mask.
1226     */
1227    public AWTEventListener[] getAWTEventListeners(long eventMask) {
1228        lockAWT();
1229        try {
1230            SecurityManager security = System.getSecurityManager();
1231            if (security != null) {
1232                security.checkPermission(awtEventsManager.permission);
1233            }
1234            return awtEventsManager.getAWTEventListeners(eventMask);
1235        } finally {
1236            unlockAWT();
1237        }
1238    }
1239
1240    /**
1241     * Dispatch AWT event.
1242     *
1243     * @param event
1244     *            the event.
1245     */
1246    void dispatchAWTEvent(AWTEvent event) {
1247        awtEventsManager.dispatchAWTEvent(event);
1248    }
1249
1250    /**
1251     * The Class AWTEventsManager.
1252     */
1253    final class AWTEventsManager {
1254
1255        /**
1256         * The permission.
1257         */
1258        AWTPermission permission = new AWTPermission("listenToAllAWTEvents"); //$NON-NLS-1$
1259
1260        /**
1261         * The listeners.
1262         */
1263        private final AWTListenerList<AWTEventListenerProxy> listeners = new AWTListenerList<AWTEventListenerProxy>();
1264
1265        /**
1266         * Adds the AWT event listener.
1267         *
1268         * @param listener
1269         *            the listener.
1270         * @param eventMask
1271         *            the event mask.
1272         */
1273        void addAWTEventListener(AWTEventListener listener, long eventMask) {
1274            if (listener != null) {
1275                listeners.addUserListener(new AWTEventListenerProxy(eventMask, listener));
1276            }
1277        }
1278
1279        /**
1280         * Removes the AWT event listener.
1281         *
1282         * @param listener
1283         *            the listener.
1284         */
1285        void removeAWTEventListener(AWTEventListener listener) {
1286            if (listener != null) {
1287                for (AWTEventListenerProxy proxy : listeners.getUserListeners()) {
1288                    if (listener == proxy.getListener()) {
1289                        listeners.removeUserListener(proxy);
1290                        return;
1291                    }
1292                }
1293            }
1294        }
1295
1296        /**
1297         * Gets the AWT event listeners.
1298         *
1299         * @return the AWT event listeners.
1300         */
1301        AWTEventListener[] getAWTEventListeners() {
1302            HashSet<EventListener> listenersSet = new HashSet<EventListener>();
1303            for (AWTEventListenerProxy proxy : listeners.getUserListeners()) {
1304                listenersSet.add(proxy.getListener());
1305            }
1306            return listenersSet.toArray(new AWTEventListener[listenersSet.size()]);
1307        }
1308
1309        /**
1310         * Gets the AWT event listeners.
1311         *
1312         * @param eventMask
1313         *            the event mask.
1314         * @return the AWT event listeners.
1315         */
1316        AWTEventListener[] getAWTEventListeners(long eventMask) {
1317            HashSet<EventListener> listenersSet = new HashSet<EventListener>();
1318            for (AWTEventListenerProxy proxy : listeners.getUserListeners()) {
1319                if ((proxy.getEventMask() & eventMask) == eventMask) {
1320                    listenersSet.add(proxy.getListener());
1321                }
1322            }
1323            return listenersSet.toArray(new AWTEventListener[listenersSet.size()]);
1324        }
1325
1326        /**
1327         * Dispatch AWT event.
1328         *
1329         * @param event
1330         *            the event.
1331         */
1332        void dispatchAWTEvent(AWTEvent event) {
1333            AWTEvent.EventDescriptor descriptor = eventTypeLookup.getEventDescriptor(event);
1334            if (descriptor == null) {
1335                return;
1336            }
1337            for (AWTEventListenerProxy proxy : listeners.getUserListeners()) {
1338                if ((proxy.getEventMask() & descriptor.eventMask) != 0) {
1339                    proxy.eventDispatched(event);
1340                }
1341            }
1342        }
1343    }
1344
1345    /**
1346     * The Class AutoNumber.
1347     */
1348    static final class AutoNumber {
1349
1350        /**
1351         * The next component.
1352         */
1353        int nextComponent = 0;
1354
1355        /**
1356         * The next canvas.
1357         */
1358        int nextCanvas = 0;
1359
1360        /**
1361         * The next panel.
1362         */
1363        int nextPanel = 0;
1364
1365        /**
1366         * The next window.
1367         */
1368        int nextWindow = 0;
1369
1370        /**
1371         * The next frame.
1372         */
1373        int nextFrame = 0;
1374
1375        /**
1376         * The next dialog.
1377         */
1378        int nextDialog = 0;
1379
1380        /**
1381         * The next button.
1382         */
1383        int nextButton = 0;
1384
1385        /**
1386         * The next menu component.
1387         */
1388        int nextMenuComponent = 0;
1389
1390        /**
1391         * The next label.
1392         */
1393        int nextLabel = 0;
1394
1395        /**
1396         * The next check box.
1397         */
1398        int nextCheckBox = 0;
1399
1400        /**
1401         * The next scrollbar.
1402         */
1403        int nextScrollbar = 0;
1404
1405        /**
1406         * The next scroll pane.
1407         */
1408        int nextScrollPane = 0;
1409
1410        /**
1411         * The next list.
1412         */
1413        int nextList = 0;
1414
1415        /**
1416         * The next choice.
1417         */
1418        int nextChoice = 0;
1419
1420        /**
1421         * The next file dialog.
1422         */
1423        int nextFileDialog = 0;
1424
1425        /**
1426         * The next text area.
1427         */
1428        int nextTextArea = 0;
1429
1430        /**
1431         * The next text field.
1432         */
1433        int nextTextField = 0;
1434    }
1435
1436    private class Lock {
1437    }
1438
1439    /**
1440     * The lock.
1441     */
1442    private final Object lock = new Lock();
1443
1444}
1445