2148 lines · 79.7 KB · Java
RawDownload
/* * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.awt; import java.awt.*;import static java.awt.RenderingHints.*;import java.awt.dnd.*;import java.awt.dnd.peer.DragSourceContextPeer;import java.awt.peer.*;import java.awt.event.WindowEvent;import java.awt.event.KeyEvent;import java.awt.image.*;import java.awt.TrayIcon;import java.awt.SystemTray;import java.net.URL;import java.util.*;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;import sun.util.logging.PlatformLogger;import sun.misc.SoftCache;import sun.font.FontDesignMetrics;import sun.awt.im.InputContext;import sun.awt.image.*;import sun.security.action.GetPropertyAction;import sun.security.action.GetBooleanAction;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.security.AccessController;import java.security.PrivilegedAction;import java.security.PrivilegedActionException;import java.security.PrivilegedExceptionAction; public abstract class SunToolkit extends Toolkit    implements WindowClosingSupport, WindowClosingListener,    ComponentFactory, InputMethodSupport, KeyboardFocusManagerPeerProvider {     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.SunToolkit");     /* Load debug settings for native code */    static {        if (AccessController.doPrivileged(new GetBooleanAction("sun.awt.nativedebug"))) {            DebugSettings.init();        }    };     /**     * Special mask for the UngrabEvent events, in addition to the     * public masks defined in AWTEvent.  Should be used as the mask     * value for Toolkit.addAWTEventListener.     */    public static final int GRAB_EVENT_MASK = 0x80000000;     private static Method  wakeupMethod;    /* The key to put()/get() the PostEventQueue into/from the AppContext.     */    private static final String POST_EVENT_QUEUE_KEY = "PostEventQueue";     /**     * Number of buttons.     * By default it's taken from the system. If system value does not     * fit into int type range, use our own MAX_BUTTONS_SUPPORT value.     */    protected static int numberOfButtons = 0;      /* XFree standard mention 24 buttons as maximum:     * http://www.xfree86.org/current/mouse.4.html     * We workaround systems supporting more than 24 buttons.     * Otherwise, we have to use long type values as masks     * which leads to API change.     * InputEvent.BUTTON_DOWN_MASK may contain only 21 masks due to     * the 4-bytes limit for the int type. (CR 6799099)     * One more bit is reserved for FIRST_HIGH_BIT.     */    public final static int MAX_BUTTONS_SUPPORTED = 20;     public SunToolkit() {        Runnable initEQ = new Runnable() {            public void run () {                EventQueue eventQueue;                 String eqName = System.getProperty("AWT.EventQueueClass",                                                   "java.awt.EventQueue");                 try {                    eventQueue = (EventQueue)Class.forName(eqName).newInstance();                } catch (Exception e) {                    e.printStackTrace();                    System.err.println("Failed loading " + eqName + ": " + e);                    eventQueue = new EventQueue();                }                AppContext appContext = AppContext.getAppContext();                appContext.put(AppContext.EVENT_QUEUE_KEY, eventQueue);                 PostEventQueue postEventQueue = new PostEventQueue(eventQueue);                appContext.put(POST_EVENT_QUEUE_KEY, postEventQueue);            }        };         initEQ.run();    }     public boolean useBufferPerWindow() {        return false;    }     public abstract WindowPeer createWindow(Window target)        throws HeadlessException;     public abstract FramePeer createFrame(Frame target)        throws HeadlessException;     public abstract DialogPeer createDialog(Dialog target)        throws HeadlessException;     public abstract ButtonPeer createButton(Button target)        throws HeadlessException;     public abstract TextFieldPeer createTextField(TextField target)        throws HeadlessException;     public abstract ChoicePeer createChoice(Choice target)        throws HeadlessException;     public abstract LabelPeer createLabel(Label target)        throws HeadlessException;     public abstract ListPeer createList(java.awt.List target)        throws HeadlessException;     public abstract CheckboxPeer createCheckbox(Checkbox target)        throws HeadlessException;     public abstract ScrollbarPeer createScrollbar(Scrollbar target)        throws HeadlessException;     public abstract ScrollPanePeer createScrollPane(ScrollPane target)        throws HeadlessException;     public abstract TextAreaPeer createTextArea(TextArea target)        throws HeadlessException;     public abstract FileDialogPeer createFileDialog(FileDialog target)        throws HeadlessException;     public abstract MenuBarPeer createMenuBar(MenuBar target)        throws HeadlessException;     public abstract MenuPeer createMenu(Menu target)        throws HeadlessException;     public abstract PopupMenuPeer createPopupMenu(PopupMenu target)        throws HeadlessException;     public abstract MenuItemPeer createMenuItem(MenuItem target)        throws HeadlessException;     public abstract CheckboxMenuItemPeer createCheckboxMenuItem(        CheckboxMenuItem target)        throws HeadlessException;     public abstract DragSourceContextPeer createDragSourceContextPeer(        DragGestureEvent dge)        throws InvalidDnDOperationException;     public abstract TrayIconPeer createTrayIcon(TrayIcon target)        throws HeadlessException, AWTException;     public abstract SystemTrayPeer createSystemTray(SystemTray target);     public abstract boolean isTraySupported();     public abstract FontPeer getFontPeer(String name, int style);     public abstract RobotPeer createRobot(Robot target, GraphicsDevice screen)        throws AWTException;     public abstract KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)        throws HeadlessException;     /**     * The AWT lock is typically only used on Unix platforms to synchronize     * access to Xlib, OpenGL, etc.  However, these methods are implemented     * in SunToolkit so that they can be called from shared code (e.g.     * from the OGL pipeline) or from the X11 pipeline regardless of whether     * XToolkit or MToolkit is currently in use.  There are native macros     * (such as AWT_LOCK) defined in awt.h, so if the implementation of these     * methods is changed, make sure it is compatible with the native macros.     *     * Note: The following methods (awtLock(), awtUnlock(), etc) should be     * used in place of:     *     synchronized (getAWTLock()) {     *         ...     *     }     *     * By factoring these methods out specially, we are able to change the     * implementation of these methods (e.g. use more advanced locking     * mechanisms) without impacting calling code.     *     * Sample usage:     *     private void doStuffWithXlib() {     *         assert !SunToolkit.isAWTLockHeldByCurrentThread();     *         SunToolkit.awtLock();     *         try {     *             ...     *             XlibWrapper.XDoStuff();     *         } finally {     *             SunToolkit.awtUnlock();     *         }     *     }     */     private static final ReentrantLock AWT_LOCK = new ReentrantLock();    private static final Condition AWT_LOCK_COND = AWT_LOCK.newCondition();     public static final void awtLock() {        AWT_LOCK.lock();    }     public static final boolean awtTryLock() {        return AWT_LOCK.tryLock();    }     public static final void awtUnlock() {        AWT_LOCK.unlock();    }     public static final void awtLockWait()        throws InterruptedException    {        AWT_LOCK_COND.await();    }     public static final void awtLockWait(long timeout)        throws InterruptedException    {        AWT_LOCK_COND.await(timeout, TimeUnit.MILLISECONDS);    }     public static final void awtLockNotify() {        AWT_LOCK_COND.signal();    }     public static final void awtLockNotifyAll() {        AWT_LOCK_COND.signalAll();    }     public static final boolean isAWTLockHeldByCurrentThread() {        return AWT_LOCK.isHeldByCurrentThread();    }     /*     * Create a new AppContext, along with its EventQueue, for a     * new ThreadGroup.  Browser code, for example, would use this     * method to create an AppContext & EventQueue for an Applet.     */    public static AppContext createNewAppContext() {        ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();        // Create appContext before initialization of EventQueue, so all        // the calls to AppContext.getAppContext() from EventQueue ctor        // return correct values        AppContext appContext = new AppContext(threadGroup);         EventQueue eventQueue;        String eqName = System.getProperty("AWT.EventQueueClass",                                           "java.awt.EventQueue");        try {            eventQueue = (EventQueue)Class.forName(eqName).newInstance();        } catch (Exception e) {            System.err.println("Failed loading " + eqName + ": " + e);            eventQueue = new EventQueue();        }        appContext.put(AppContext.EVENT_QUEUE_KEY, eventQueue);         PostEventQueue postEventQueue = new PostEventQueue(eventQueue);        appContext.put(POST_EVENT_QUEUE_KEY, postEventQueue);         return appContext;    }     public static Field getField(final Class klass, final String fieldName) {        return AccessController.doPrivileged(new PrivilegedAction<Field>() {            public Field run() {                try {                    Field field = klass.getDeclaredField(fieldName);                    assert (field != null);                    field.setAccessible(true);                    return field;                } catch (SecurityException e) {                    assert false;                } catch (NoSuchFieldException e) {                    assert false;                }                return null;            }//run        });    }     static void wakeupEventQueue(EventQueue q, boolean isShutdown){        if (wakeupMethod == null){            wakeupMethod = (Method)AccessController.doPrivileged(new PrivilegedAction(){                    public Object run(){                        try {                            Method method  = EventQueue.class.getDeclaredMethod("wakeup",new Class [] {Boolean.TYPE} );                            if (method != null) {                                method.setAccessible(true);                            }                            return method;                        } catch (NoSuchMethodException e) {                            assert false;                        } catch (SecurityException e) {                            assert false;                        }                        return null;                    }//run                });        }        try{            if (wakeupMethod != null){                wakeupMethod.invoke(q, new Object[]{Boolean.valueOf(isShutdown)});            }        } catch (InvocationTargetException e){            assert false;        } catch (IllegalAccessException e) {            assert false;        }    }     /*     * Fetch the peer associated with the given target (as specified     * in the peer creation method).  This can be used to determine     * things like what the parent peer is.  If the target is null     * or the target can't be found (either because the a peer was     * never created for it or the peer was disposed), a null will     * be returned.     */    protected static Object targetToPeer(Object target) {        if (target != null && !GraphicsEnvironment.isHeadless()) {            return AWTAutoShutdown.getInstance().getPeer(target);        }        return null;    }     protected static void targetCreatedPeer(Object target, Object peer) {        if (target != null && peer != null &&            !GraphicsEnvironment.isHeadless())        {            AWTAutoShutdown.getInstance().registerPeer(target, peer);        }    }     protected static void targetDisposedPeer(Object target, Object peer) {        if (target != null && peer != null &&            !GraphicsEnvironment.isHeadless())        {            AWTAutoShutdown.getInstance().unregisterPeer(target, peer);        }    }     // Maps from non-Component/MenuComponent to AppContext.    // WeakHashMap<Component,AppContext>    private static final Map appContextMap =        Collections.synchronizedMap(new WeakHashMap());     /**     * Sets the appContext field of target. If target is not a Component or     * MenuComponent, this returns false.     */    private static boolean setAppContext(Object target,                                         AppContext context) {        if (target instanceof Component) {            AWTAccessor.getComponentAccessor().                setAppContext((Component)target, context);        } else if (target instanceof MenuComponent) {            AWTAccessor.getMenuComponentAccessor().                setAppContext((MenuComponent)target, context);        } else {            return false;        }        return true;    }     /**     * Returns the appContext field for target. If target is not a     * Component or MenuComponent this returns null.     */    private static AppContext getAppContext(Object target) {        if (target instanceof Component) {            return AWTAccessor.getComponentAccessor().                       getAppContext((Component)target);        } else if (target instanceof MenuComponent) {            return AWTAccessor.getMenuComponentAccessor().                       getAppContext((MenuComponent)target);        } else {            return null;        }    }     /*     * Fetch the AppContext associated with the given target.     * This can be used to determine things like which EventQueue     * to use for posting events to a Component.  If the target is     * null or the target can't be found, a null with be returned.     */    public static AppContext targetToAppContext(Object target) {        if (target == null || GraphicsEnvironment.isHeadless()) {            return null;        }        AppContext context = getAppContext(target);        if (context == null) {            // target is not a Component/MenuComponent, try the            // appContextMap.            context = (AppContext)appContextMap.get(target);        }        return context;    }      /**      * Sets the synchronous status of focus requests on lightweight      * components in the specified window to the specified value.      * If the boolean parameter is <code>true</code> then the focus      * requests on lightweight components will be performed      * synchronously, if it is <code>false</code>, then asynchronously.      * By default, all windows have their lightweight request status      * set to asynchronous.      * <p>      * The application can only set the status of lightweight focus      * requests to synchronous for any of its windows if it doesn't      * perform focus transfers between different heavyweight containers.      * In this case the observable focus behaviour is the same as with      * asynchronous status.      * <p>      * If the application performs focus transfer between different      * heavyweight containers and sets the lightweight focus request      * status to synchronous for any of its windows, then further focus      * behaviour is unspecified.      * <p>      * @param    w window for which the lightweight focus request status      *             should be set      * @param    status the value of lightweight focus request status      */     public static void setLWRequestStatus(Window changed,boolean status){        AWTAccessor.getWindowAccessor().setLWRequestStatus(changed, status);    };     public static void checkAndSetPolicy(Container cont, boolean isSwingCont)    {        FocusTraversalPolicy defaultPolicy = KeyboardFocusManager            .getCurrentKeyboardFocusManager().getDefaultFocusTraversalPolicy();         String toolkitName = Toolkit.getDefaultToolkit().getClass().getName();        // if this is not XAWT then use default policy        // because Swing change it        if (!"sun.awt.X11.XToolkit".equals(toolkitName)) {            cont.setFocusTraversalPolicy(defaultPolicy);            return;        }         String policyName = defaultPolicy.getClass().getName();         if (DefaultFocusTraversalPolicy.class != defaultPolicy.getClass()) {            // Policy was changed            // Check if it is awt policy or swing policy            // If it is Swing policy we shouldn't use it in AWT frames            // If it is AWT policy  we shouldn't use it in Swing frames            // Otherwise we should use this policy            if (policyName.startsWith("java.awt.")) {                // AWT                if (isSwingCont) {                    // Can't use AWT policy in Swing windows - should use Swing's one.                    defaultPolicy = createLayoutPolicy();                } else {

Lines 1–500 of 2148.