Save This Page
Home » openjdk-7 » sun » awt » [javadoc | source]
    1   /*
    2    * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package sun.awt;
   27   
   28   import java.awt;
   29   import static java.awt.RenderingHints.*;
   30   import java.awt.dnd;
   31   import java.awt.dnd.peer.DragSourceContextPeer;
   32   import java.awt.peer;
   33   import java.awt.event.WindowEvent;
   34   import java.awt.event.KeyEvent;
   35   import java.awt.image;
   36   import java.awt.TrayIcon;
   37   import java.awt.SystemTray;
   38   import java.net.URL;
   39   import java.util;
   40   import java.util.concurrent.TimeUnit;
   41   import java.util.concurrent.locks.Condition;
   42   import java.util.concurrent.locks.Lock;
   43   import java.util.concurrent.locks.ReentrantLock;
   44   import sun.util.logging.PlatformLogger;
   45   import sun.misc.SoftCache;
   46   import sun.font.FontDesignMetrics;
   47   import sun.awt.im.InputContext;
   48   import sun.awt.image;
   49   import sun.security.action.GetPropertyAction;
   50   import sun.security.action.GetBooleanAction;
   51   import java.lang.reflect.Field;
   52   import java.lang.reflect.Method;
   53   import java.lang.reflect.Constructor;
   54   import java.lang.reflect.InvocationTargetException;
   55   import java.security.AccessController;
   56   import java.security.PrivilegedAction;
   57   import java.security.PrivilegedActionException;
   58   import java.security.PrivilegedExceptionAction;
   59   
   60   public abstract class SunToolkit extends Toolkit
   61       implements WindowClosingSupport, WindowClosingListener,
   62       ComponentFactory, InputMethodSupport, KeyboardFocusManagerPeerProvider {
   63   
   64       private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.SunToolkit");
   65   
   66       /* Load debug settings for native code */
   67       static {
   68           if (AccessController.doPrivileged(new GetBooleanAction("sun.awt.nativedebug"))) {
   69               DebugSettings.init();
   70           }
   71       };
   72   
   73       /**
   74        * Special mask for the UngrabEvent events, in addition to the
   75        * public masks defined in AWTEvent.  Should be used as the mask
   76        * value for Toolkit.addAWTEventListener.
   77        */
   78       public static final int GRAB_EVENT_MASK = 0x80000000;
   79   
   80       private static Method  wakeupMethod;
   81       /* The key to put()/get() the PostEventQueue into/from the AppContext.
   82        */
   83       private static final String POST_EVENT_QUEUE_KEY = "PostEventQueue";
   84   
   85       /**
   86        * Number of buttons.
   87        * By default it's taken from the system. If system value does not
   88        * fit into int type range, use our own MAX_BUTTONS_SUPPORT value.
   89        */
   90       protected static int numberOfButtons = 0;
   91   
   92   
   93       /* XFree standard mention 24 buttons as maximum:
   94        * http://www.xfree86.org/current/mouse.4.html
   95        * We workaround systems supporting more than 24 buttons.
   96        * Otherwise, we have to use long type values as masks
   97        * which leads to API change.
   98        * InputEvent.BUTTON_DOWN_MASK may contain only 21 masks due to
   99        * the 4-bytes limit for the int type. (CR 6799099)
  100        * One more bit is reserved for FIRST_HIGH_BIT.
  101        */
  102       public final static int MAX_BUTTONS_SUPPORTED = 20;
  103   
  104       public SunToolkit() {
  105           Runnable initEQ = new Runnable() {
  106               public void run () {
  107                   EventQueue eventQueue;
  108   
  109                   String eqName = System.getProperty("AWT.EventQueueClass",
  110                                                      "java.awt.EventQueue");
  111   
  112                   try {
  113                       eventQueue = (EventQueue)Class.forName(eqName).newInstance();
  114                   } catch (Exception e) {
  115                       e.printStackTrace();
  116                       System.err.println("Failed loading " + eqName + ": " + e);
  117                       eventQueue = new EventQueue();
  118                   }
  119                   AppContext appContext = AppContext.getAppContext();
  120                   appContext.put(AppContext.EVENT_QUEUE_KEY, eventQueue);
  121   
  122                   PostEventQueue postEventQueue = new PostEventQueue(eventQueue);
  123                   appContext.put(POST_EVENT_QUEUE_KEY, postEventQueue);
  124               }
  125           };
  126   
  127           initEQ.run();
  128       }
  129   
  130       public boolean useBufferPerWindow() {
  131           return false;
  132       }
  133   
  134       public abstract WindowPeer createWindow(Window target)
  135           throws HeadlessException;
  136   
  137       public abstract FramePeer createFrame(Frame target)
  138           throws HeadlessException;
  139   
  140       public abstract DialogPeer createDialog(Dialog target)
  141           throws HeadlessException;
  142   
  143       public abstract ButtonPeer createButton(Button target)
  144           throws HeadlessException;
  145   
  146       public abstract TextFieldPeer createTextField(TextField target)
  147           throws HeadlessException;
  148   
  149       public abstract ChoicePeer createChoice(Choice target)
  150           throws HeadlessException;
  151   
  152       public abstract LabelPeer createLabel(Label target)
  153           throws HeadlessException;
  154   
  155       public abstract ListPeer createList(java.awt.List target)
  156           throws HeadlessException;
  157   
  158       public abstract CheckboxPeer createCheckbox(Checkbox target)
  159           throws HeadlessException;
  160   
  161       public abstract ScrollbarPeer createScrollbar(Scrollbar target)
  162           throws HeadlessException;
  163   
  164       public abstract ScrollPanePeer createScrollPane(ScrollPane target)
  165           throws HeadlessException;
  166   
  167       public abstract TextAreaPeer createTextArea(TextArea target)
  168           throws HeadlessException;
  169   
  170       public abstract FileDialogPeer createFileDialog(FileDialog target)
  171           throws HeadlessException;
  172   
  173       public abstract MenuBarPeer createMenuBar(MenuBar target)
  174           throws HeadlessException;
  175   
  176       public abstract MenuPeer createMenu(Menu target)
  177           throws HeadlessException;
  178   
  179       public abstract PopupMenuPeer createPopupMenu(PopupMenu target)
  180           throws HeadlessException;
  181   
  182       public abstract MenuItemPeer createMenuItem(MenuItem target)
  183           throws HeadlessException;
  184   
  185       public abstract CheckboxMenuItemPeer createCheckboxMenuItem(
  186           CheckboxMenuItem target)
  187           throws HeadlessException;
  188   
  189       public abstract DragSourceContextPeer createDragSourceContextPeer(
  190           DragGestureEvent dge)
  191           throws InvalidDnDOperationException;
  192   
  193       public abstract TrayIconPeer createTrayIcon(TrayIcon target)
  194           throws HeadlessException, AWTException;
  195   
  196       public abstract SystemTrayPeer createSystemTray(SystemTray target);
  197   
  198       public abstract boolean isTraySupported();
  199   
  200       public abstract FontPeer getFontPeer(String name, int style);
  201   
  202       public abstract RobotPeer createRobot(Robot target, GraphicsDevice screen)
  203           throws AWTException;
  204   
  205       public abstract KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
  206           throws HeadlessException;
  207   
  208       /**
  209        * The AWT lock is typically only used on Unix platforms to synchronize
  210        * access to Xlib, OpenGL, etc.  However, these methods are implemented
  211        * in SunToolkit so that they can be called from shared code (e.g.
  212        * from the OGL pipeline) or from the X11 pipeline regardless of whether
  213        * XToolkit or MToolkit is currently in use.  There are native macros
  214        * (such as AWT_LOCK) defined in awt.h, so if the implementation of these
  215        * methods is changed, make sure it is compatible with the native macros.
  216        *
  217        * Note: The following methods (awtLock(), awtUnlock(), etc) should be
  218        * used in place of:
  219        *     synchronized (getAWTLock()) {
  220        *         ...
  221        *     }
  222        *
  223        * By factoring these methods out specially, we are able to change the
  224        * implementation of these methods (e.g. use more advanced locking
  225        * mechanisms) without impacting calling code.
  226        *
  227        * Sample usage:
  228        *     private void doStuffWithXlib() {
  229        *         assert !SunToolkit.isAWTLockHeldByCurrentThread();
  230        *         SunToolkit.awtLock();
  231        *         try {
  232        *             ...
  233        *             XlibWrapper.XDoStuff();
  234        *         } finally {
  235        *             SunToolkit.awtUnlock();
  236        *         }
  237        *     }
  238        */
  239   
  240       private static final ReentrantLock AWT_LOCK = new ReentrantLock();
  241       private static final Condition AWT_LOCK_COND = AWT_LOCK.newCondition();
  242   
  243       public static final void awtLock() {
  244           AWT_LOCK.lock();
  245       }
  246   
  247       public static final boolean awtTryLock() {
  248           return AWT_LOCK.tryLock();
  249       }
  250   
  251       public static final void awtUnlock() {
  252           AWT_LOCK.unlock();
  253       }
  254   
  255       public static final void awtLockWait()
  256           throws InterruptedException
  257       {
  258           AWT_LOCK_COND.await();
  259       }
  260   
  261       public static final void awtLockWait(long timeout)
  262           throws InterruptedException
  263       {
  264           AWT_LOCK_COND.await(timeout, TimeUnit.MILLISECONDS);
  265       }
  266   
  267       public static final void awtLockNotify() {
  268           AWT_LOCK_COND.signal();
  269       }
  270   
  271       public static final void awtLockNotifyAll() {
  272           AWT_LOCK_COND.signalAll();
  273       }
  274   
  275       public static final boolean isAWTLockHeldByCurrentThread() {
  276           return AWT_LOCK.isHeldByCurrentThread();
  277       }
  278   
  279       /*
  280        * Create a new AppContext, along with its EventQueue, for a
  281        * new ThreadGroup.  Browser code, for example, would use this
  282        * method to create an AppContext & EventQueue for an Applet.
  283        */
  284       public static AppContext createNewAppContext() {
  285           ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
  286           // Create appContext before initialization of EventQueue, so all
  287           // the calls to AppContext.getAppContext() from EventQueue ctor
  288           // return correct values
  289           AppContext appContext = new AppContext(threadGroup);
  290   
  291           EventQueue eventQueue;
  292           String eqName = System.getProperty("AWT.EventQueueClass",
  293                                              "java.awt.EventQueue");
  294           try {
  295               eventQueue = (EventQueue)Class.forName(eqName).newInstance();
  296           } catch (Exception e) {
  297               System.err.println("Failed loading " + eqName + ": " + e);
  298               eventQueue = new EventQueue();
  299           }
  300           appContext.put(AppContext.EVENT_QUEUE_KEY, eventQueue);
  301   
  302           PostEventQueue postEventQueue = new PostEventQueue(eventQueue);
  303           appContext.put(POST_EVENT_QUEUE_KEY, postEventQueue);
  304   
  305           return appContext;
  306       }
  307   
  308       public static Field getField(final Class klass, final String fieldName) {
  309           return AccessController.doPrivileged(new PrivilegedAction<Field>() {
  310               public Field run() {
  311                   try {
  312                       Field field = klass.getDeclaredField(fieldName);
  313                       assert (field != null);
  314                       field.setAccessible(true);
  315                       return field;
  316                   } catch (SecurityException e) {
  317                       assert false;
  318                   } catch (NoSuchFieldException e) {
  319                       assert false;
  320                   }
  321                   return null;
  322               }//run
  323           });
  324       }
  325   
  326       static void wakeupEventQueue(EventQueue q, boolean isShutdown){
  327           if (wakeupMethod == null){
  328               wakeupMethod = (Method)AccessController.doPrivileged(new PrivilegedAction(){
  329                       public Object run(){
  330                           try {
  331                               Method method  = EventQueue.class.getDeclaredMethod("wakeup",new Class [] {Boolean.TYPE} );
  332                               if (method != null) {
  333                                   method.setAccessible(true);
  334                               }
  335                               return method;
  336                           } catch (NoSuchMethodException e) {
  337                               assert false;
  338                           } catch (SecurityException e) {
  339                               assert false;
  340                           }
  341                           return null;
  342                       }//run
  343                   });
  344           }
  345           try{
  346               if (wakeupMethod != null){
  347                   wakeupMethod.invoke(q, new Object[]{Boolean.valueOf(isShutdown)});
  348               }
  349           } catch (InvocationTargetException e){
  350               assert false;
  351           } catch (IllegalAccessException e) {
  352               assert false;
  353           }
  354       }
  355   
  356       /*
  357        * Fetch the peer associated with the given target (as specified
  358        * in the peer creation method).  This can be used to determine
  359        * things like what the parent peer is.  If the target is null
  360        * or the target can't be found (either because the a peer was
  361        * never created for it or the peer was disposed), a null will
  362        * be returned.
  363        */
  364       protected static Object targetToPeer(Object target) {
  365           if (target != null && !GraphicsEnvironment.isHeadless()) {
  366               return AWTAutoShutdown.getInstance().getPeer(target);
  367           }
  368           return null;
  369       }
  370   
  371       protected static void targetCreatedPeer(Object target, Object peer) {
  372           if (target != null && peer != null &&
  373               !GraphicsEnvironment.isHeadless())
  374           {
  375               AWTAutoShutdown.getInstance().registerPeer(target, peer);
  376           }
  377       }
  378   
  379       protected static void targetDisposedPeer(Object target, Object peer) {
  380           if (target != null && peer != null &&
  381               !GraphicsEnvironment.isHeadless())
  382           {
  383               AWTAutoShutdown.getInstance().unregisterPeer(target, peer);
  384           }
  385       }
  386   
  387       // Maps from non-Component/MenuComponent to AppContext.
  388       // WeakHashMap<Component,AppContext>
  389       private static final Map appContextMap =
  390           Collections.synchronizedMap(new WeakHashMap());
  391   
  392       /**
  393        * Sets the appContext field of target. If target is not a Component or
  394        * MenuComponent, this returns false.
  395        */
  396       private static boolean setAppContext(Object target,
  397                                            AppContext context) {
  398           if (target instanceof Component) {
  399               AWTAccessor.getComponentAccessor().
  400                   setAppContext((Component)target, context);
  401           } else if (target instanceof MenuComponent) {
  402               AWTAccessor.getMenuComponentAccessor().
  403                   setAppContext((MenuComponent)target, context);
  404           } else {
  405               return false;
  406           }
  407           return true;
  408       }
  409   
  410       /**
  411        * Returns the appContext field for target. If target is not a
  412        * Component or MenuComponent this returns null.
  413        */
  414       private static AppContext getAppContext(Object target) {
  415           if (target instanceof Component) {
  416               return AWTAccessor.getComponentAccessor().
  417                          getAppContext((Component)target);
  418           } else if (target instanceof MenuComponent) {
  419               return AWTAccessor.getMenuComponentAccessor().
  420                          getAppContext((MenuComponent)target);
  421           } else {
  422               return null;
  423           }
  424       }
  425   
  426       /*
  427        * Fetch the AppContext associated with the given target.
  428        * This can be used to determine things like which EventQueue
  429        * to use for posting events to a Component.  If the target is
  430        * null or the target can't be found, a null with be returned.
  431        */
  432       public static AppContext targetToAppContext(Object target) {
  433           if (target == null || GraphicsEnvironment.isHeadless()) {
  434               return null;
  435           }
  436           AppContext context = getAppContext(target);
  437           if (context == null) {
  438               // target is not a Component/MenuComponent, try the
  439               // appContextMap.
  440               context = (AppContext)appContextMap.get(target);
  441           }
  442           return context;
  443       }
  444   
  445        /**
  446         * Sets the synchronous status of focus requests on lightweight
  447         * components in the specified window to the specified value.
  448         * If the boolean parameter is <code>true</code> then the focus
  449         * requests on lightweight components will be performed
  450         * synchronously, if it is <code>false</code>, then asynchronously.
  451         * By default, all windows have their lightweight request status
  452         * set to asynchronous.
  453         * <p>
  454         * The application can only set the status of lightweight focus
  455         * requests to synchronous for any of its windows if it doesn't
  456         * perform focus transfers between different heavyweight containers.
  457         * In this case the observable focus behaviour is the same as with
  458         * asynchronous status.
  459         * <p>
  460         * If the application performs focus transfer between different
  461         * heavyweight containers and sets the lightweight focus request
  462         * status to synchronous for any of its windows, then further focus
  463         * behaviour is unspecified.
  464         * <p>
  465         * @param    w window for which the lightweight focus request status
  466         *             should be set
  467         * @param    status the value of lightweight focus request status
  468         */
  469   
  470       public static void setLWRequestStatus(Window changed,boolean status){
  471           AWTAccessor.getWindowAccessor().setLWRequestStatus(changed, status);
  472       };
  473   
  474       public static void checkAndSetPolicy(Container cont, boolean isSwingCont)
  475       {
  476           FocusTraversalPolicy defaultPolicy = KeyboardFocusManager
  477               .getCurrentKeyboardFocusManager().getDefaultFocusTraversalPolicy();
  478   
  479           String toolkitName = Toolkit.getDefaultToolkit().getClass().getName();
  480           // if this is not XAWT then use default policy
  481           // because Swing change it
  482           if (!"sun.awt.X11.XToolkit".equals(toolkitName)) {
  483               cont.setFocusTraversalPolicy(defaultPolicy);
  484               return;
  485           }
  486   
  487           String policyName = defaultPolicy.getClass().getName();
  488   
  489           if (DefaultFocusTraversalPolicy.class != defaultPolicy.getClass()) {
  490               // Policy was changed
  491               // Check if it is awt policy or swing policy
  492               // If it is Swing policy we shouldn't use it in AWT frames
  493               // If it is AWT policy  we shouldn't use it in Swing frames
  494               // Otherwise we should use this policy
  495               if (policyName.startsWith("java.awt.")) {
  496                   // AWT
  497                   if (isSwingCont) {
  498                       // Can't use AWT policy in Swing windows - should use Swing's one.
  499                       defaultPolicy = createLayoutPolicy();
  500                   } else {
  501                       // New awt policy.
  502                   }
  503               } else if (policyName.startsWith("javax.swing.")) {
  504                   if (isSwingCont) {
  505                       // New Swing's policy
  506                   } else {
  507                       defaultPolicy = new DefaultFocusTraversalPolicy();
  508                   }
  509               }
  510           } else {
  511               // Policy is default, use different default policy for swing
  512               if (isSwingCont) {
  513                   defaultPolicy = createLayoutPolicy();
  514               }
  515           }
  516           cont.setFocusTraversalPolicy(defaultPolicy);
  517       }
  518   
  519       private static FocusTraversalPolicy createLayoutPolicy() {
  520           FocusTraversalPolicy policy = null;
  521           try {
  522               Class layoutPolicyClass =
  523                   Class.forName("javax.swing.LayoutFocusTraversalPolicy");
  524               policy = (FocusTraversalPolicy) layoutPolicyClass.newInstance();
  525           }
  526           catch (ClassNotFoundException e) {
  527               assert false;
  528           }
  529           catch (InstantiationException e) {
  530               assert false;
  531           }
  532           catch (IllegalAccessException e) {
  533               assert false;
  534           }
  535   
  536           return policy;
  537       }
  538   
  539       /*
  540        * Insert a mapping from target to AppContext, for later retrieval
  541        * via targetToAppContext() above.
  542        */
  543       public static void insertTargetMapping(Object target, AppContext appContext) {
  544           if (!GraphicsEnvironment.isHeadless()) {
  545               if (!setAppContext(target, appContext)) {
  546                   // Target is not a Component/MenuComponent, use the private Map
  547                   // instead.
  548                   appContextMap.put(target, appContext);
  549               }
  550           }
  551       }
  552   
  553       /*
  554        * Post an AWTEvent to the Java EventQueue, using the PostEventQueue
  555        * to avoid possibly calling client code (EventQueueSubclass.postEvent())
  556        * on the toolkit (AWT-Windows/AWT-Motif) thread.  This function should
  557        * not be called under another lock since it locks the EventQueue.
  558        * See bugids 4632918, 4526597.
  559        */
  560       public static void postEvent(AppContext appContext, AWTEvent event) {
  561           if (event == null) {
  562               throw new NullPointerException();
  563           }
  564           // All events posted via this method are system-generated.
  565           // Placing the following call here reduces considerably the
  566           // number of places throughout the toolkit that would
  567           // otherwise have to be modified to precisely identify
  568           // system-generated events.
  569           setSystemGenerated(event);
  570           AppContext eventContext = targetToAppContext(event.getSource());
  571           if (eventContext != null && !eventContext.equals(appContext)) {
  572               log.fine("Event posted on wrong app context : " + event);
  573           }
  574           PostEventQueue postEventQueue =
  575               (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
  576           if (postEventQueue != null) {
  577               postEventQueue.postEvent(event);
  578           }
  579       }
  580   
  581       /*
  582        * Post AWTEvent of high priority.
  583        */
  584       public static void postPriorityEvent(final AWTEvent e) {
  585           PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() {
  586                   public void run() {
  587                       AWTAccessor.getAWTEventAccessor().setPosted(e);
  588                       ((Component)e.getSource()).dispatchEvent(e);
  589                   }
  590               }, PeerEvent.ULTIMATE_PRIORITY_EVENT);
  591           postEvent(targetToAppContext(e.getSource()), pe);
  592       }
  593   
  594       private static final Lock flushLock = new ReentrantLock();
  595       private static boolean isFlushingPendingEvents = false;
  596   
  597       /*
  598        * Flush any pending events which haven't been posted to the AWT
  599        * EventQueue yet.
  600        */
  601       public static void flushPendingEvents()  {
  602           flushLock.lock();
  603           try {
  604               // Don't call flushPendingEvents() recursively
  605               if (!isFlushingPendingEvents) {
  606                   isFlushingPendingEvents = true;
  607                   AppContext appContext = AppContext.getAppContext();
  608                   PostEventQueue postEventQueue =
  609                       (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
  610                   if (postEventQueue != null) {
  611                       postEventQueue.flush();
  612                   }
  613               }
  614           } finally {
  615               isFlushingPendingEvents = false;
  616               flushLock.unlock();
  617           }
  618       }
  619   
  620       public static boolean isPostEventQueueEmpty()  {
  621           AppContext appContext = AppContext.getAppContext();
  622           PostEventQueue postEventQueue =
  623               (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
  624           if (postEventQueue != null) {
  625               return postEventQueue.noEvents();
  626           } else {
  627               return true;
  628           }
  629       }
  630   
  631       /*
  632        * Execute a chunk of code on the Java event handler thread for the
  633        * given target.  Does not wait for the execution to occur before
  634        * returning to the caller.
  635        */
  636       public static void executeOnEventHandlerThread(Object target,
  637                                                      Runnable runnable) {
  638           executeOnEventHandlerThread(new PeerEvent(target, runnable, PeerEvent.PRIORITY_EVENT));
  639       }
  640   
  641       /*
  642        * Fixed 5064013: the InvocationEvent time should be equals
  643        * the time of the ActionEvent
  644        */
  645       public static void executeOnEventHandlerThread(Object target,
  646                                                      Runnable runnable,
  647                                                      final long when) {
  648           executeOnEventHandlerThread(new PeerEvent(target, runnable, PeerEvent.PRIORITY_EVENT){
  649                   public long getWhen(){
  650                       return when;
  651                   }
  652               });
  653       }
  654   
  655       /*
  656        * Execute a chunk of code on the Java event handler thread for the
  657        * given target.  Does not wait for the execution to occur before
  658        * returning to the caller.
  659        */
  660       public static void executeOnEventHandlerThread(PeerEvent peerEvent) {
  661           postEvent(targetToAppContext(peerEvent.getSource()), peerEvent);
  662       }
  663   
  664       /*
  665        * Execute a chunk of code on the Java event handler thread. The
  666        * method takes into account provided AppContext and sets
  667        * <code>SunToolkit.getDefaultToolkit()</code> as a target of the
  668        * event. See 6451487 for detailes.
  669        * Does not wait for the execution to occur before returning to
  670        * the caller.
  671        */
  672        public static void invokeLaterOnAppContext(
  673           AppContext appContext, Runnable dispatcher)
  674        {
  675           postEvent(appContext,
  676               new PeerEvent(Toolkit.getDefaultToolkit(), dispatcher,
  677                   PeerEvent.PRIORITY_EVENT));
  678        }
  679   
  680       /*
  681        * Execute a chunk of code on the Java event handler thread for the
  682        * given target.  Waits for the execution to occur before returning
  683        * to the caller.
  684        */
  685       public static void executeOnEDTAndWait(Object target, Runnable runnable)
  686           throws InterruptedException, InvocationTargetException
  687       {
  688           if (EventQueue.isDispatchThread()) {
  689               throw new Error("Cannot call executeOnEDTAndWait from any event dispatcher thread");
  690           }
  691   
  692           class AWTInvocationLock {}
  693           Object lock = new AWTInvocationLock();
  694   
  695           PeerEvent event = new PeerEvent(target, runnable, lock, true, PeerEvent.PRIORITY_EVENT);
  696   
  697           synchronized (lock) {
  698               executeOnEventHandlerThread(event);
  699               while(!event.isDispatched()) {
  700                   lock.wait();
  701               }
  702           }
  703   
  704           Throwable eventThrowable = event.getThrowable();
  705           if (eventThrowable != null) {
  706               throw new InvocationTargetException(eventThrowable);
  707           }
  708       }
  709   
  710       /*
  711        * Returns true if the calling thread is the event dispatch thread
  712        * contained within AppContext which associated with the given target.
  713        * Use this call to ensure that a given task is being executed
  714        * (or not being) on the event dispatch thread for the given target.
  715        */
  716       public static boolean isDispatchThreadForAppContext(Object target) {
  717           AppContext appContext = targetToAppContext(target);
  718           EventQueue eq = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
  719   
  720           AWTAccessor.EventQueueAccessor accessor = AWTAccessor.getEventQueueAccessor();
  721           return accessor.isDispatchThreadImpl(eq);
  722       }
  723   
  724       public Dimension getScreenSize() {
  725           return new Dimension(getScreenWidth(), getScreenHeight());
  726       }
  727       protected abstract int getScreenWidth();
  728       protected abstract int getScreenHeight();
  729   
  730       public FontMetrics getFontMetrics(Font font) {
  731           return FontDesignMetrics.getMetrics(font);
  732       }
  733   
  734       public String[] getFontList() {
  735           String[] hardwiredFontList = {
  736               Font.DIALOG, Font.SANS_SERIF, Font.SERIF, Font.MONOSPACED,
  737               Font.DIALOG_INPUT
  738   
  739               // -- Obsolete font names from 1.0.2.  It was decided that
  740               // -- getFontList should not return these old names:
  741               //    "Helvetica", "TimesRoman", "Courier", "ZapfDingbats"
  742           };
  743           return hardwiredFontList;
  744       }
  745   
  746       public PanelPeer createPanel(Panel target) {
  747           return (PanelPeer)createComponent(target);
  748       }
  749   
  750       public CanvasPeer createCanvas(Canvas target) {
  751           return (CanvasPeer)createComponent(target);
  752       }
  753   
  754       /**
  755        * Disables erasing of background on the canvas before painting if
  756        * this is supported by the current toolkit. It is recommended to
  757        * call this method early, before the Canvas becomes displayable,
  758        * because some Toolkit implementations do not support changing
  759        * this property once the Canvas becomes displayable.
  760        */
  761       public void disableBackgroundErase(Canvas canvas) {
  762           disableBackgroundEraseImpl(canvas);
  763       }
  764   
  765       /**
  766        * Disables the native erasing of the background on the given
  767        * component before painting if this is supported by the current
  768        * toolkit. This only has an effect for certain components such as
  769        * Canvas, Panel and Window. It is recommended to call this method
  770        * early, before the Component becomes displayable, because some
  771        * Toolkit implementations do not support changing this property
  772        * once the Component becomes displayable.
  773        */
  774       public void disableBackgroundErase(Component component) {
  775           disableBackgroundEraseImpl(component);
  776       }
  777   
  778       private void disableBackgroundEraseImpl(Component component) {
  779           AWTAccessor.getComponentAccessor().setBackgroundEraseDisabled(component, true);
  780       }
  781   
  782       /**
  783        * Returns the value of "sun.awt.noerasebackground" property. Default
  784        * value is {@code false}.
  785        */
  786       public static boolean getSunAwtNoerasebackground() {
  787           return AccessController.doPrivileged(new GetBooleanAction("sun.awt.noerasebackground"));
  788       }
  789   
  790       /**
  791        * Returns the value of "sun.awt.erasebackgroundonresize" property. Default
  792        * value is {@code false}.
  793        */
  794       public static boolean getSunAwtErasebackgroundonresize() {
  795           return AccessController.doPrivileged(new GetBooleanAction("sun.awt.erasebackgroundonresize"));
  796       }
  797   
  798   
  799       static final SoftCache imgCache = new SoftCache();
  800   
  801       static Image getImageFromHash(Toolkit tk, URL url) {
  802           SecurityManager sm = System.getSecurityManager();
  803           if (sm != null) {
  804               try {
  805                   java.security.Permission perm =
  806                       url.openConnection().getPermission();
  807                   if (perm != null) {
  808                       try {
  809                           sm.checkPermission(perm);
  810                       } catch (SecurityException se) {
  811                           // fallback to checkRead/checkConnect for pre 1.2
  812                           // security managers
  813                           if ((perm instanceof java.io.FilePermission) &&
  814                               perm.getActions().indexOf("read") != -1) {
  815                               sm.checkRead(perm.getName());
  816                           } else if ((perm instanceof
  817                               java.net.SocketPermission) &&
  818                               perm.getActions().indexOf("connect") != -1) {
  819                               sm.checkConnect(url.getHost(), url.getPort());
  820                           } else {
  821                               throw se;
  822                           }
  823                       }
  824                   }
  825               } catch (java.io.IOException ioe) {
  826                       sm.checkConnect(url.getHost(), url.getPort());
  827               }
  828           }
  829           synchronized (imgCache) {
  830               Image img = (Image)imgCache.get(url);
  831               if (img == null) {
  832                   try {
  833                       img = tk.createImage(new URLImageSource(url));
  834                       imgCache.put(url, img);
  835                   } catch (Exception e) {
  836                   }
  837               }
  838               return img;
  839           }
  840       }
  841   
  842       static Image getImageFromHash(Toolkit tk,
  843                                                  String filename) {
  844           SecurityManager security = System.getSecurityManager();
  845           if (security != null) {
  846               security.checkRead(filename);
  847           }
  848           synchronized (imgCache) {
  849               Image img = (Image)imgCache.get(filename);
  850               if (img == null) {
  851                   try {
  852                       img = tk.createImage(new FileImageSource(filename));
  853                       imgCache.put(filename, img);
  854                   } catch (Exception e) {
  855                   }
  856               }
  857               return img;
  858           }
  859       }
  860   
  861       public Image getImage(String filename) {
  862           return getImageFromHash(this, filename);
  863       }
  864   
  865       public Image getImage(URL url) {
  866           return getImageFromHash(this, url);
  867       }
  868   
  869       public Image createImage(String filename) {
  870           SecurityManager security = System.getSecurityManager();
  871           if (security != null) {
  872               security.checkRead(filename);
  873           }
  874           return createImage(new FileImageSource(filename));
  875       }
  876   
  877       public Image createImage(URL url) {
  878           SecurityManager sm = System.getSecurityManager();
  879           if (sm != null) {
  880               try {
  881                   java.security.Permission perm =
  882                       url.openConnection().getPermission();
  883                   if (perm != null) {
  884                       try {
  885                           sm.checkPermission(perm);
  886                       } catch (SecurityException se) {
  887                           // fallback to checkRead/checkConnect for pre 1.2
  888                           // security managers
  889                           if ((perm instanceof java.io.FilePermission) &&
  890                               perm.getActions().indexOf("read") != -1) {
  891                               sm.checkRead(perm.getName());
  892                           } else if ((perm instanceof
  893                               java.net.SocketPermission) &&
  894                               perm.getActions().indexOf("connect") != -1) {
  895                               sm.checkConnect(url.getHost(), url.getPort());
  896                           } else {
  897                               throw se;
  898                           }
  899                       }
  900                   }
  901               } catch (java.io.IOException ioe) {
  902                       sm.checkConnect(url.getHost(), url.getPort());
  903               }
  904           }
  905           return createImage(new URLImageSource(url));
  906       }
  907   
  908       public Image createImage(byte[] data, int offset, int length) {
  909           return createImage(new ByteArrayImageSource(data, offset, length));
  910       }
  911   
  912       public Image createImage(ImageProducer producer) {
  913           return new ToolkitImage(producer);
  914       }
  915   
  916       public int checkImage(Image img, int w, int h, ImageObserver o) {
  917           if (!(img instanceof ToolkitImage)) {
  918               return ImageObserver.ALLBITS;
  919           }
  920   
  921           ToolkitImage tkimg = (ToolkitImage)img;
  922           int repbits;
  923           if (w == 0 || h == 0) {
  924               repbits = ImageObserver.ALLBITS;
  925           } else {
  926               repbits = tkimg.getImageRep().check(o);
  927           }
  928           return tkimg.check(o) | repbits;
  929       }
  930   
  931       public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
  932           if (w == 0 || h == 0) {
  933               return true;
  934           }
  935   
  936           // Must be a ToolkitImage
  937           if (!(img instanceof ToolkitImage)) {
  938               return true;
  939           }
  940   
  941           ToolkitImage tkimg = (ToolkitImage)img;
  942           if (tkimg.hasError()) {
  943               if (o != null) {
  944                   o.imageUpdate(img, ImageObserver.ERROR|ImageObserver.ABORT,
  945                                 -1, -1, -1, -1);
  946               }
  947               return false;
  948           }
  949           ImageRepresentation ir = tkimg.getImageRep();
  950           return ir.prepare(o);
  951       }
  952   
  953       /**
  954        * Scans {@code imageList} for best-looking image of specified dimensions.
  955        * Image can be scaled and/or padded with transparency.
  956        */
  957       public static BufferedImage getScaledIconImage(java.util.List<Image> imageList, int width, int height) {
  958           if (width == 0 || height == 0) {
  959               return null;
  960           }
  961           Image bestImage = null;
  962           int bestWidth = 0;
  963           int bestHeight = 0;
  964           double bestSimilarity = 3; //Impossibly high value
  965           double bestScaleFactor = 0;
  966           for (Iterator<Image> i = imageList.iterator();i.hasNext();) {
  967               //Iterate imageList looking for best matching image.
  968               //'Similarity' measure is defined as good scale factor and small insets.
  969               //best possible similarity is 0 (no scale, no insets).
  970               //It's found while the experiments that good-looking result is achieved
  971               //with scale factors x1, x3/4, x2/3, xN, x1/N.
  972               Image im = i.next();
  973               if (im == null) {
  974                   if (log.isLoggable(PlatformLogger.FINER)) {
  975                       log.finer("SunToolkit.getScaledIconImage: " +
  976                                 "Skipping the image passed into Java because it's null.");
  977                   }
  978                   continue;
  979               }
  980               if (im instanceof ToolkitImage) {
  981                   ImageRepresentation ir = ((ToolkitImage)im).getImageRep();
  982                   ir.reconstruct(ImageObserver.ALLBITS);
  983               }
  984               int iw;
  985               int ih;
  986               try {
  987                   iw = im.getWidth(null);
  988                   ih = im.getHeight(null);
  989               } catch (Exception e){
  990                   if (log.isLoggable(PlatformLogger.FINER)) {
  991                       log.finer("SunToolkit.getScaledIconImage: " +
  992                                 "Perhaps the image passed into Java is broken. Skipping this icon.");
  993                   }
  994                   continue;
  995               }
  996               if (iw > 0 && ih > 0) {
  997                   //Calc scale factor
  998                   double scaleFactor = Math.min((double)width / (double)iw,
  999                                                 (double)height / (double)ih);
 1000                   //Calculate scaled image dimensions
 1001                   //adjusting scale factor to nearest "good" value
 1002                   int adjw = 0;
 1003                   int adjh = 0;
 1004                   double scaleMeasure = 1; //0 - best (no) scale, 1 - impossibly bad
 1005                   if (scaleFactor >= 2) {
 1006                       //Need to enlarge image more than twice
 1007                       //Round down scale factor to multiply by integer value
 1008                       scaleFactor = Math.floor(scaleFactor);
 1009                       adjw = iw * (int)scaleFactor;
 1010                       adjh = ih * (int)scaleFactor;
 1011                       scaleMeasure = 1.0 - 0.5 / scaleFactor;
 1012                   } else if (scaleFactor >= 1) {
 1013                       //Don't scale
 1014                       scaleFactor = 1.0;
 1015                       adjw = iw;
 1016                       adjh = ih;
 1017                       scaleMeasure = 0;
 1018                   } else if (scaleFactor >= 0.75) {
 1019                       //Multiply by 3/4
 1020                       scaleFactor = 0.75;
 1021                       adjw = iw * 3 / 4;
 1022                       adjh = ih * 3 / 4;
 1023                       scaleMeasure = 0.3;
 1024                   } else if (scaleFactor >= 0.6666) {
 1025                       //Multiply by 2/3
 1026                       scaleFactor = 0.6666;
 1027                       adjw = iw * 2 / 3;
 1028                       adjh = ih * 2 / 3;
 1029                       scaleMeasure = 0.33;
 1030                   } else {
 1031                       //Multiply size by 1/scaleDivider
 1032                       //where scaleDivider is minimum possible integer
 1033                       //larger than 1/scaleFactor
 1034                       double scaleDivider = Math.ceil(1.0 / scaleFactor);
 1035                       scaleFactor = 1.0 / scaleDivider;
 1036                       adjw = (int)Math.round((double)iw / scaleDivider);
 1037                       adjh = (int)Math.round((double)ih / scaleDivider);
 1038                       scaleMeasure = 1.0 - 1.0 / scaleDivider;
 1039                   }
 1040                   double similarity = ((double)width - (double)adjw) / (double)width +
 1041                       ((double)height - (double)adjh) / (double)height + //Large padding is bad
 1042                       scaleMeasure; //Large rescale is bad
 1043                   if (similarity < bestSimilarity) {
 1044                       bestSimilarity = similarity;
 1045                       bestScaleFactor = scaleFactor;
 1046                       bestImage = im;
 1047                       bestWidth = adjw;
 1048                       bestHeight = adjh;
 1049                   }
 1050                   if (similarity == 0) break;
 1051               }
 1052           }
 1053           if (bestImage == null) {
 1054               //No images were found, possibly all are broken
 1055               return null;
 1056           }
 1057           BufferedImage bimage =
 1058               new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
 1059           Graphics2D g = bimage.createGraphics();
 1060           g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
 1061                              RenderingHints.VALUE_INTERPOLATION_BILINEAR);
 1062           try {
 1063               int x = (width - bestWidth) / 2;
 1064               int y = (height - bestHeight) / 2;
 1065               if (log.isLoggable(PlatformLogger.FINER)) {
 1066                   log.finer("WWindowPeer.getScaledIconData() result : " +
 1067                           "w : " + width + " h : " + height +
 1068                           " iW : " + bestImage.getWidth(null) + " iH : " + bestImage.getHeight(null) +
 1069                           " sim : " + bestSimilarity + " sf : " + bestScaleFactor +
 1070                           " adjW : " + bestWidth + " adjH : " + bestHeight +
 1071                           " x : " + x + " y : " + y);
 1072               }
 1073               g.drawImage(bestImage, x, y, bestWidth, bestHeight, null);
 1074           } finally {
 1075               g.dispose();
 1076           }
 1077           return bimage;
 1078       }
 1079   
 1080       public static DataBufferInt getScaledIconData(java.util.List<Image> imageList, int width, int height) {
 1081           BufferedImage bimage = getScaledIconImage(imageList, width, height);
 1082           if (bimage == null) {
 1083                if (log.isLoggable(PlatformLogger.FINER)) {
 1084                    log.finer("SunToolkit.getScaledIconData: " +
 1085                              "Perhaps the image passed into Java is broken. Skipping this icon.");
 1086                }
 1087               return null;
 1088           }
 1089           Raster raster = bimage.getRaster();
 1090           DataBuffer buffer = raster.getDataBuffer();
 1091           return (DataBufferInt)buffer;
 1092       }
 1093   
 1094       protected EventQueue getSystemEventQueueImpl() {
 1095           return getSystemEventQueueImplPP();
 1096       }
 1097   
 1098       // Package private implementation
 1099       static EventQueue getSystemEventQueueImplPP() {
 1100           return getSystemEventQueueImplPP(AppContext.getAppContext());
 1101       }
 1102   
 1103       public static EventQueue getSystemEventQueueImplPP(AppContext appContext) {
 1104           EventQueue theEventQueue =
 1105               (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
 1106           return theEventQueue;
 1107       }
 1108   
 1109       /**
 1110        * Give native peers the ability to query the native container
 1111        * given a native component (eg the direct parent may be lightweight).
 1112        */
 1113       public static Container getNativeContainer(Component c) {
 1114           return Toolkit.getNativeContainer(c);
 1115       }
 1116   
 1117       /**
 1118        * Gives native peers the ability to query the closest HW component.
 1119        * If the given component is heavyweight, then it returns this. Otherwise,
 1120        * it goes one level up in the hierarchy and tests next component.
 1121        */
 1122       public static Component getHeavyweightComponent(Component c) {
 1123           while (c != null && AWTAccessor.getComponentAccessor().isLightweight(c)) {
 1124               c = AWTAccessor.getComponentAccessor().getParent(c);
 1125           }
 1126           return c;
 1127       }
 1128   
 1129       /**
 1130        * Returns a new input method window, with behavior as specified in
 1131        * {@link java.awt.im.spi.InputMethodContext#createInputMethodWindow}.
 1132        * If the inputContext is not null, the window should return it from its
 1133        * getInputContext() method. The window needs to implement
 1134        * sun.awt.im.InputMethodWindow.
 1135        * <p>
 1136        * SunToolkit subclasses can override this method to return better input
 1137        * method windows.
 1138        */
 1139       public Window createInputMethodWindow(String title, InputContext context) {
 1140           return new sun.awt.im.SimpleInputMethodWindow(title, context);
 1141       }
 1142   
 1143       /**
 1144        * Returns whether enableInputMethods should be set to true for peered
 1145        * TextComponent instances on this platform. False by default.
 1146        */
 1147       public boolean enableInputMethodsForTextComponent() {
 1148           return false;
 1149       }
 1150   
 1151       private static Locale startupLocale = null;
 1152   
 1153       /**
 1154        * Returns the locale in which the runtime was started.
 1155        */
 1156       public static Locale getStartupLocale() {
 1157           if (startupLocale == null) {
 1158               String language, region, country, variant;
 1159               language = (String) AccessController.doPrivileged(
 1160                               new GetPropertyAction("user.language", "en"));
 1161               // for compatibility, check for old user.region property
 1162               region = (String) AccessController.doPrivileged(
 1163                               new GetPropertyAction("user.region"));
 1164               if (region != null) {
 1165                   // region can be of form country, country_variant, or _variant
 1166                   int i = region.indexOf('_');
 1167                   if (i >= 0) {
 1168                       country = region.substring(0, i);
 1169                       variant = region.substring(i + 1);
 1170                   } else {
 1171                       country = region;
 1172                       variant = "";
 1173                   }
 1174               } else {
 1175                   country = (String) AccessController.doPrivileged(
 1176                                   new GetPropertyAction("user.country", ""));
 1177                   variant = (String) AccessController.doPrivileged(
 1178                                   new GetPropertyAction("user.variant", ""));
 1179               }
 1180               startupLocale = new Locale(language, country, variant);
 1181           }
 1182           return startupLocale;
 1183       }
 1184   
 1185       /**
 1186        * Returns the default keyboard locale of the underlying operating system
 1187        */
 1188       public Locale getDefaultKeyboardLocale() {
 1189           return getStartupLocale();
 1190       }
 1191   
 1192       private static String dataTransfererClassName = null;
 1193   
 1194       protected static void setDataTransfererClassName(String className) {
 1195           dataTransfererClassName = className;
 1196       }
 1197   
 1198       public static String getDataTransfererClassName() {
 1199           if (dataTransfererClassName == null) {
 1200               Toolkit.getDefaultToolkit(); // transferer set during toolkit init
 1201           }
 1202           return dataTransfererClassName;
 1203       }
 1204   
 1205       // Support for window closing event notifications
 1206       private transient WindowClosingListener windowClosingListener = null;
 1207       /**
 1208        * @see sun.awt.WindowClosingSupport#getWindowClosingListener
 1209        */
 1210       public WindowClosingListener getWindowClosingListener() {
 1211           return windowClosingListener;
 1212       }
 1213       /**
 1214        * @see sun.awt.WindowClosingSupport#setWindowClosingListener
 1215        */
 1216       public void setWindowClosingListener(WindowClosingListener wcl) {
 1217           windowClosingListener = wcl;
 1218       }
 1219   
 1220       /**
 1221        * @see sun.awt.WindowClosingListener#windowClosingNotify
 1222        */
 1223       public RuntimeException windowClosingNotify(WindowEvent event) {
 1224           if (windowClosingListener != null) {
 1225               return windowClosingListener.windowClosingNotify(event);
 1226           } else {
 1227               return null;
 1228           }
 1229       }
 1230       /**
 1231        * @see sun.awt.WindowClosingListener#windowClosingDelivered
 1232        */
 1233       public RuntimeException windowClosingDelivered(WindowEvent event) {
 1234           if (windowClosingListener != null) {
 1235               return windowClosingListener.windowClosingDelivered(event);
 1236           } else {
 1237               return null;
 1238           }
 1239       }
 1240   
 1241       private static DefaultMouseInfoPeer mPeer = null;
 1242   
 1243       protected synchronized MouseInfoPeer getMouseInfoPeer() {
 1244           if (mPeer == null) {
 1245               mPeer = new DefaultMouseInfoPeer();
 1246           }
 1247           return mPeer;
 1248       }
 1249   
 1250   
 1251       /**
 1252        * Returns whether default toolkit needs the support of the xembed
 1253        * from embedding host(if any).
 1254        * @return <code>true</code>, if XEmbed is needed, <code>false</code> otherwise
 1255        */
 1256       public static boolean needsXEmbed() {
 1257           String noxembed = (String) AccessController.
 1258               doPrivileged(new GetPropertyAction("sun.awt.noxembed", "false"));
 1259           if ("true".equals(noxembed)) {
 1260               return false;
 1261           }
 1262   
 1263           Toolkit tk = Toolkit.getDefaultToolkit();
 1264           if (tk instanceof SunToolkit) {
 1265               // SunToolkit descendants should override this method to specify
 1266               // concrete behavior
 1267               return ((SunToolkit)tk).needsXEmbedImpl();
 1268           } else {
 1269               // Non-SunToolkit doubtly might support XEmbed
 1270               return false;
 1271           }
 1272       }
 1273   
 1274       /**
 1275        * Returns whether this toolkit needs the support of the xembed
 1276        * from embedding host(if any).
 1277        * @return <code>true</code>, if XEmbed is needed, <code>false</code> otherwise
 1278        */
 1279       protected boolean needsXEmbedImpl() {
 1280           return false;
 1281       }
 1282   
 1283       private static Dialog.ModalExclusionType DEFAULT_MODAL_EXCLUSION_TYPE = null;
 1284   
 1285       /**
 1286        * Returns whether the XEmbed server feature is requested by
 1287        * developer.  If true, Toolkit should return an
 1288        * XEmbed-server-enabled CanvasPeer instead of the ordinary CanvasPeer.
 1289        */
 1290       protected final boolean isXEmbedServerRequested() {
 1291           return AccessController.doPrivileged(new GetBooleanAction("sun.awt.xembedserver"));
 1292       }
 1293   
 1294       /**
 1295        * Returns whether the modal exclusion API is supported by the current toolkit.
 1296        * When it isn't supported, calling <code>setModalExcluded</code> has no
 1297        * effect, and <code>isModalExcluded</code> returns false for all windows.
 1298        *
 1299        * @return true if modal exclusion is supported by the toolkit, false otherwise
 1300        *
 1301        * @see sun.awt.SunToolkit#setModalExcluded(java.awt.Window)
 1302        * @see sun.awt.SunToolkit#isModalExcluded(java.awt.Window)
 1303        *
 1304        * @since 1.5
 1305        */
 1306       public static boolean isModalExcludedSupported()
 1307       {
 1308           Toolkit tk = Toolkit.getDefaultToolkit();
 1309           return tk.isModalExclusionTypeSupported(DEFAULT_MODAL_EXCLUSION_TYPE);
 1310       }
 1311       /*
 1312        * Default implementation for isModalExcludedSupportedImpl(), returns false.
 1313        *
 1314        * @see sun.awt.windows.WToolkit#isModalExcludeSupportedImpl
 1315        * @see sun.awt.X11.XToolkit#isModalExcludeSupportedImpl
 1316        *
 1317        * @since 1.5
 1318        */
 1319       protected boolean isModalExcludedSupportedImpl()
 1320       {
 1321           return false;
 1322       }
 1323   
 1324       /*
 1325        * Sets this window to be excluded from being modally blocked. When the
 1326        * toolkit supports modal exclusion and this method is called, input
 1327        * events, focus transfer and z-order will continue to work for the
 1328        * window, it's owned windows and child components, even in the
 1329        * presence of a modal dialog.
 1330        * For details on which <code>Window</code>s are normally blocked
 1331        * by modal dialog, see {@link java.awt.Dialog}.
 1332        * Invoking this method when the modal exclusion API is not supported by
 1333        * the current toolkit has no effect.
 1334        * @param window Window to be marked as not modally blocked
 1335        * @see java.awt.Dialog
 1336        * @see java.awt.Dialog#setModal(boolean)
 1337        * @see sun.awt.SunToolkit#isModalExcludedSupported
 1338        * @see sun.awt.SunToolkit#isModalExcluded(java.awt.Window)
 1339        */
 1340       public static void setModalExcluded(Window window)
 1341       {
 1342           if (DEFAULT_MODAL_EXCLUSION_TYPE == null) {
 1343               DEFAULT_MODAL_EXCLUSION_TYPE = Dialog.ModalExclusionType.APPLICATION_EXCLUDE;
 1344           }
 1345           window.setModalExclusionType(DEFAULT_MODAL_EXCLUSION_TYPE);
 1346       }
 1347   
 1348       /*
 1349        * Returns whether the specified window is blocked by modal dialogs.
 1350        * If the modal exclusion API isn't supported by the current toolkit,
 1351        * it returns false for all windows.
 1352        *
 1353        * @param window Window to test for modal exclusion
 1354        *
 1355        * @return true if the window is modal excluded, false otherwise. If
 1356        * the modal exclusion isn't supported by the current Toolkit, false
 1357        * is returned
 1358        *
 1359        * @see sun.awt.SunToolkit#isModalExcludedSupported
 1360        * @see sun.awt.SunToolkit#setModalExcluded(java.awt.Window)
 1361        *
 1362        * @since 1.5
 1363        */
 1364       public static boolean isModalExcluded(Window window)
 1365       {
 1366           if (DEFAULT_MODAL_EXCLUSION_TYPE == null) {
 1367               DEFAULT_MODAL_EXCLUSION_TYPE = Dialog.ModalExclusionType.APPLICATION_EXCLUDE;
 1368           }
 1369           return window.getModalExclusionType().compareTo(DEFAULT_MODAL_EXCLUSION_TYPE) >= 0;
 1370       }
 1371   
 1372       /**
 1373        * Overridden in XToolkit and WToolkit
 1374        */
 1375       public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
 1376           return (modalityType == Dialog.ModalityType.MODELESS) ||
 1377                  (modalityType == Dialog.ModalityType.APPLICATION_MODAL);
 1378       }
 1379   
 1380       /**
 1381        * Overridden in XToolkit and WToolkit
 1382        */
 1383       public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
 1384           return (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE);
 1385       }
 1386   
 1387       ///////////////////////////////////////////////////////////////////////////
 1388       //
 1389       // The following is used by the Java Plug-in to coordinate dialog modality
 1390       // between containing applications (browsers, ActiveX containers etc) and
 1391       // the AWT.
 1392       //
 1393       ///////////////////////////////////////////////////////////////////////////
 1394   
 1395       private ModalityListenerList modalityListeners = new ModalityListenerList();
 1396   
 1397       public void addModalityListener(ModalityListener listener) {
 1398           modalityListeners.add(listener);
 1399       }
 1400   
 1401       public void removeModalityListener(ModalityListener listener) {
 1402           modalityListeners.remove(listener);
 1403       }
 1404   
 1405       public void notifyModalityPushed(Dialog dialog) {
 1406           notifyModalityChange(ModalityEvent.MODALITY_PUSHED, dialog);
 1407       }
 1408   
 1409       public void notifyModalityPopped(Dialog dialog) {
 1410           notifyModalityChange(ModalityEvent.MODALITY_POPPED, dialog);
 1411       }
 1412   
 1413       final void notifyModalityChange(int id, Dialog source) {
 1414           ModalityEvent ev = new ModalityEvent(source, modalityListeners, id);
 1415           ev.dispatch();
 1416       }
 1417   
 1418       static class ModalityListenerList implements ModalityListener {
 1419   
 1420           Vector<ModalityListener> listeners = new Vector<ModalityListener>();
 1421   
 1422           void add(ModalityListener listener) {
 1423               listeners.addElement(listener);
 1424           }
 1425   
 1426           void remove(ModalityListener listener) {
 1427               listeners.removeElement(listener);
 1428           }
 1429   
 1430           public void modalityPushed(ModalityEvent ev) {
 1431               Iterator<ModalityListener> it = listeners.iterator();
 1432               while (it.hasNext()) {
 1433                   it.next().modalityPushed(ev);
 1434               }
 1435           }
 1436   
 1437           public void modalityPopped(ModalityEvent ev) {
 1438               Iterator<ModalityListener> it = listeners.iterator();
 1439               while (it.hasNext()) {
 1440                   it.next().modalityPopped(ev);
 1441               }
 1442           }
 1443       } // end of class ModalityListenerList
 1444   
 1445       ///////////////////////////////////////////////////////////////////////////
 1446       // End Plug-in code
 1447       ///////////////////////////////////////////////////////////////////////////
 1448   
 1449       public static boolean isLightweightOrUnknown(Component comp) {
 1450           if (comp.isLightweight()
 1451               || !(getDefaultToolkit() instanceof SunToolkit))
 1452           {
 1453               return true;
 1454           }
 1455           return !(comp instanceof Button
 1456               || comp instanceof Canvas
 1457               || comp instanceof Checkbox
 1458               || comp instanceof Choice
 1459               || comp instanceof Label
 1460               || comp instanceof java.awt.List
 1461               || comp instanceof Panel
 1462               || comp instanceof Scrollbar
 1463               || comp instanceof ScrollPane
 1464               || comp instanceof TextArea
 1465               || comp instanceof TextField
 1466               || comp instanceof Window);
 1467       }
 1468   
 1469       public static Method getMethod(final Class clz, final String methodName, final Class[] params) {
 1470           Method res = null;
 1471           try {
 1472               res = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
 1473                       public Method run() throws Exception {
 1474                           Method m = clz.getDeclaredMethod(methodName, params);
 1475                           m.setAccessible(true);
 1476                           return m;
 1477                       }
 1478                   });
 1479           } catch (PrivilegedActionException ex) {
 1480               ex.printStackTrace();
 1481           }
 1482           return res;
 1483       }
 1484   
 1485       public static class OperationTimedOut extends RuntimeException {
 1486           public OperationTimedOut(String msg) {
 1487               super(msg);
 1488           }
 1489           public OperationTimedOut() {
 1490           }
 1491       }
 1492       public static class InfiniteLoop extends RuntimeException {
 1493       }
 1494   
 1495       public static class IllegalThreadException extends RuntimeException {
 1496           public IllegalThreadException(String msg) {
 1497               super(msg);
 1498           }
 1499           public IllegalThreadException() {
 1500           }
 1501       }
 1502   
 1503       public static final int DEFAULT_WAIT_TIME = 10000;
 1504       private static final int MAX_ITERS = 20;
 1505       private static final int MIN_ITERS = 0;
 1506       private static final int MINIMAL_EDELAY = 0;
 1507   
 1508       /**
 1509        * Parameterless version of realsync which uses default timout (see DEFAUL_WAIT_TIME).
 1510        */
 1511       public void realSync() throws OperationTimedOut, InfiniteLoop {
 1512           realSync(DEFAULT_WAIT_TIME);
 1513       }
 1514   
 1515       /**
 1516        * Forces toolkit to synchronize with the native windowing
 1517        * sub-system, flushing all pending work and waiting for all the
 1518        * events to be processed.  This method guarantees that after
 1519        * return no additional Java events will be generated, unless
 1520        * cause by user. Obviously, the method cannot be used on the
 1521        * event dispatch thread (EDT). In case it nevertheless gets
 1522        * invoked on this thread, the method throws the
 1523        * IllegalThreadException runtime exception.
 1524        *
 1525        * <p> This method allows to write tests without explicit timeouts
 1526        * or wait for some event.  Example:
 1527        * <code>
 1528        * Frame f = ...;
 1529        * f.setVisible(true);
 1530        * ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
 1531        * </code>
 1532        *
 1533        * <p> After realSync, <code>f</code> will be completely visible
 1534        * on the screen, its getLocationOnScreen will be returning the
 1535        * right result and it will be the focus owner.
 1536        *
 1537        * <p> Another example:
 1538        * <code>
 1539        * b.requestFocus();
 1540        * ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
 1541        * </code>
 1542        *
 1543        * <p> After realSync, <code>b</code> will be focus owner.
 1544        *
 1545        * <p> Notice that realSync isn't guaranteed to work if recurring
 1546        * actions occur, such as if during processing of some event
 1547        * another request which may generate some events occurs.  By
 1548        * default, sync tries to perform as much as {@value MAX_ITERS}
 1549        * cycles of event processing, allowing for roughly {@value
 1550        * MAX_ITERS} additional requests.
 1551        *
 1552        * <p> For example, requestFocus() generates native request, which
 1553        * generates one or two Java focus events, which then generate a
 1554        * serie of paint events, a serie of Java focus events, which then
 1555        * generate a serie of paint events which then are processed -
 1556        * three cycles, minimum.
 1557        *
 1558        * @param timeout the maximum time to wait in milliseconds, negative means "forever".
 1559        */
 1560       public void realSync(final long timeout) throws OperationTimedOut, InfiniteLoop
 1561       {
 1562           if (EventQueue.isDispatchThread()) {
 1563               throw new IllegalThreadException("The SunToolkit.realSync() method cannot be used on the event dispatch thread (EDT).");
 1564           }
 1565           int bigLoop = 0;
 1566           do {
 1567               // Let's do sync first
 1568               sync();
 1569   
 1570               // During the wait process, when we were processing incoming
 1571               // events, we could have made some new request, which can
 1572               // generate new events.  Example: MapNotify/XSetInputFocus.
 1573               // Therefore, we dispatch them as long as there is something
 1574               // to dispatch.
 1575               int iters = 0;
 1576               while (iters < MIN_ITERS) {
 1577                   syncNativeQueue(timeout);
 1578                   iters++;
 1579               }
 1580               while (syncNativeQueue(timeout) && iters < MAX_ITERS) {
 1581                   iters++;
 1582               }
 1583               if (iters >= MAX_ITERS) {
 1584                   throw new InfiniteLoop();
 1585               }
 1586   
 1587               // native requests were dispatched by X/Window Manager or Windows
 1588               // Moreover, we processed them all on Toolkit thread
 1589               // Now wait while EDT processes them.
 1590               //
 1591               // During processing of some events (focus, for example),
 1592               // some other events could have been generated.  So, after
 1593               // waitForIdle, we may end up with full EventQueue
 1594               iters = 0;
 1595               while (iters < MIN_ITERS) {
 1596                   waitForIdle(timeout);
 1597                   iters++;
 1598               }
 1599               while (waitForIdle(timeout) && iters < MAX_ITERS) {
 1600                   iters++;
 1601               }
 1602               if (iters >= MAX_ITERS) {
 1603                   throw new InfiniteLoop();
 1604               }
 1605   
 1606               bigLoop++;
 1607               // Again, for Java events, it was simple to check for new Java
 1608               // events by checking event queue, but what if Java events
 1609               // resulted in native requests?  Therefor, check native events again.
 1610           } while ((syncNativeQueue(timeout) || waitForIdle(timeout)) && bigLoop < MAX_ITERS);
 1611       }
 1612   
 1613       /**
 1614        * Platform toolkits need to implement this method to perform the
 1615        * sync of the native queue.  The method should wait until native
 1616        * requests are processed, all native events are processed and
 1617        * corresponding Java events are generated.  Should return
 1618        * <code>true</code> if some events were processed,
 1619        * <code>false</code> otherwise.
 1620        */
 1621       protected abstract boolean syncNativeQueue(final long timeout);
 1622   
 1623       private boolean eventDispatched = false;
 1624       private boolean queueEmpty = false;
 1625       private final Object waitLock = "Wait Lock";
 1626   
 1627       static Method eqNoEvents;
 1628   
 1629       private boolean isEQEmpty() {
 1630           EventQueue queue = getSystemEventQueueImpl();
 1631           synchronized(SunToolkit.class) {
 1632               if (eqNoEvents == null) {
 1633                   eqNoEvents = getMethod(java.awt.EventQueue.class, "noEvents", null);
 1634               }
 1635           }
 1636           try {
 1637               return (Boolean)eqNoEvents.invoke(queue);
 1638           } catch (Exception e) {
 1639               e.printStackTrace();
 1640               return false;
 1641           }
 1642       }
 1643   
 1644       /**
 1645        * Waits for the Java event queue to empty.  Ensures that all
 1646        * events are processed (including paint events), and that if
 1647        * recursive events were generated, they are also processed.
 1648        * Should return <code>true</code> if more processing is
 1649        * necessary, <code>false</code> otherwise.
 1650        */
 1651       protected final boolean waitForIdle(final long timeout) {
 1652           flushPendingEvents();
 1653           boolean queueWasEmpty = isEQEmpty();
 1654           queueEmpty = false;
 1655           eventDispatched = false;
 1656           synchronized(waitLock) {
 1657               postEvent(AppContext.getAppContext(),
 1658                         new PeerEvent(getSystemEventQueueImpl(), null, PeerEvent.LOW_PRIORITY_EVENT) {
 1659                             public void dispatch() {
 1660                                 // Here we block EDT.  It could have some
 1661                                 // events, it should have dispatched them by
 1662                                 // now.  So native requests could have been
 1663                                 // generated.  First, dispatch them.  Then,
 1664                                 // flush Java events again.
 1665                                 int iters = 0;
 1666                                 while (iters < MIN_ITERS) {
 1667                                     syncNativeQueue(timeout);
 1668                                     iters++;
 1669                                 }
 1670                                 while (syncNativeQueue(timeout) && iters < MAX_ITERS) {
 1671                                     iters++;
 1672                                 }
 1673                                 flushPendingEvents();
 1674   
 1675                                 synchronized(waitLock) {
 1676                                     queueEmpty = isEQEmpty();
 1677                                     eventDispatched = true;
 1678                                     waitLock.notifyAll();
 1679                                 }
 1680                             }
 1681                         });
 1682               try {
 1683                   while (!eventDispatched) {
 1684                       waitLock.wait();
 1685                   }
 1686               } catch (InterruptedException ie) {
 1687                   return false;
 1688               }
 1689           }
 1690   
 1691           try {
 1692               Thread.sleep(MINIMAL_EDELAY);
 1693           } catch (InterruptedException ie) {
 1694               throw new RuntimeException("Interrupted");
 1695           }
 1696   
 1697           flushPendingEvents();
 1698   
 1699           // Lock to force write-cache flush for queueEmpty.
 1700           synchronized (waitLock) {
 1701               return !(queueEmpty && isEQEmpty() && queueWasEmpty);
 1702           }
 1703       }
 1704   
 1705       /**
 1706        * Grabs the mouse input for the given window.  The window must be
 1707        * visible.  The window or its children do not receive any
 1708        * additional mouse events besides those targeted to them.  All
 1709        * other events will be dispatched as before - to the respective
 1710        * targets.  This Window will receive UngrabEvent when automatic
 1711        * ungrab is about to happen.  The event can be listened to by
 1712        * installing AWTEventListener with WINDOW_EVENT_MASK.  See
 1713        * UngrabEvent class for the list of conditions when ungrab is
 1714        * about to happen.
 1715        * @see UngrabEvent
 1716        */
 1717       public abstract void grab(Window w);
 1718   
 1719       /**
 1720        * Forces ungrab.  No event will be sent.
 1721        */
 1722       public abstract void ungrab(Window w);
 1723   
 1724   
 1725       /**
 1726        * Locates the splash screen library in a platform dependent way and closes
 1727        * the splash screen. Should be invoked on first top-level frame display.
 1728        * @see java.awt.SplashScreen
 1729        * @since 1.6
 1730        */
 1731       public static native void closeSplashScreen();
 1732   
 1733       /* The following methods and variables are to support retrieving
 1734        * desktop text anti-aliasing settings
 1735        */
 1736   
 1737       /* Need an instance method because setDesktopProperty(..) is protected. */
 1738       private void fireDesktopFontPropertyChanges() {
 1739           setDesktopProperty(SunToolkit.DESKTOPFONTHINTS,
 1740                              SunToolkit.getDesktopFontHints());
 1741       }
 1742   
 1743       private static boolean checkedSystemAAFontSettings;
 1744       private static boolean useSystemAAFontSettings;
 1745       private static boolean lastExtraCondition = true;
 1746       private static RenderingHints desktopFontHints;
 1747   
 1748       /* Since Swing is the reason for this "extra condition" logic its
 1749        * worth documenting it in some detail.
 1750        * First, a goal is for Swing and applications to both retrieve and
 1751        * use the same desktop property value so that there is complete
 1752        * consistency between the settings used by JDK's Swing implementation
 1753        * and 3rd party custom Swing components, custom L&Fs and any general
 1754        * text rendering that wants to be consistent with these.
 1755        * But by default on Solaris & Linux Swing will not use AA text over
 1756        * remote X11 display (unless Xrender can be used which is TBD and may not
 1757        * always be available anyway) as that is a noticeable performance hit.
 1758        * So there needs to be a way to express that extra condition so that
 1759        * it is seen by all clients of the desktop property API.
 1760        * If this were the only condition it could be handled here as it would
 1761        * be the same for any L&F and could reasonably be considered to be
 1762        * a static behaviour of those systems.
 1763        * But GTK currently has an additional test based on locale which is
 1764        * not applied by Metal. So mixing GTK in a few locales with Metal
 1765        * would mean the last one wins.
 1766        * This could be stored per-app context which would work
 1767        * for different applets, but wouldn't help for a single application
 1768        * using GTK and some other L&F concurrently.
 1769        * But it is expected this will be addressed within GTK and the font
 1770        * system so is a temporary and somewhat unlikely harmless corner case.
 1771        */
 1772       public static void setAAFontSettingsCondition(boolean extraCondition) {
 1773           if (extraCondition != lastExtraCondition) {
 1774               lastExtraCondition = extraCondition;
 1775               if (checkedSystemAAFontSettings) {
 1776                   /* Someone already asked for this info, under a different
 1777                    * condition.
 1778                    * We'll force re-evaluation instead of replicating the
 1779                    * logic, then notify any listeners of any change.
 1780                    */
 1781                   checkedSystemAAFontSettings = false;
 1782                   Toolkit tk = Toolkit.getDefaultToolkit();
 1783                   if (tk instanceof SunToolkit) {
 1784                        ((SunToolkit)tk).fireDesktopFontPropertyChanges();
 1785                   }
 1786               }
 1787           }
 1788       }
 1789   
 1790       /* "false", "off", ""default" aren't explicitly tested, they
 1791        * just fall through to produce a null return which all are equated to
 1792        * "false".
 1793        */
 1794       private static RenderingHints getDesktopAAHintsByName(String hintname) {
 1795           Object aaHint = null;
 1796           hintname = hintname.toLowerCase(Locale.ENGLISH);
 1797           if (hintname.equals("on")) {
 1798               aaHint = VALUE_TEXT_ANTIALIAS_ON;
 1799           } else if (hintname.equals("gasp")) {
 1800               aaHint = VALUE_TEXT_ANTIALIAS_GASP;
 1801           } else if (hintname.equals("lcd") || hintname.equals("lcd_hrgb")) {
 1802               aaHint = VALUE_TEXT_ANTIALIAS_LCD_HRGB;
 1803           } else if (hintname.equals("lcd_hbgr")) {
 1804               aaHint = VALUE_TEXT_ANTIALIAS_LCD_HBGR;
 1805           } else if (hintname.equals("lcd_vrgb")) {
 1806               aaHint = VALUE_TEXT_ANTIALIAS_LCD_VRGB;
 1807           } else if (hintname.equals("lcd_vbgr")) {
 1808               aaHint = VALUE_TEXT_ANTIALIAS_LCD_VBGR;
 1809           }
 1810           if (aaHint != null) {
 1811               RenderingHints map = new RenderingHints(null);
 1812               map.put(KEY_TEXT_ANTIALIASING, aaHint);
 1813               return map;
 1814           } else {
 1815               return null;
 1816           }
 1817       }
 1818   
 1819       /* This method determines whether to use the system font settings,
 1820        * or ignore them if a L&F has specified they should be ignored, or
 1821        * to override both of these with a system property specified value.
 1822        * If the toolkit isn't a SunToolkit, (eg may be headless) then that
 1823        * system property isn't applied as desktop properties are considered
 1824        * to be inapplicable in that case. In that headless case although
 1825        * this method will return "true" the toolkit will return a null map.
 1826        */
 1827       private static boolean useSystemAAFontSettings() {
 1828           if (!checkedSystemAAFontSettings) {
 1829               useSystemAAFontSettings = true; /* initially set this true */
 1830               String systemAAFonts = null;
 1831               Toolkit tk = Toolkit.getDefaultToolkit();
 1832               if (tk instanceof SunToolkit) {
 1833                   systemAAFonts =
 1834                       (String)AccessController.doPrivileged(
 1835                            new GetPropertyAction("awt.useSystemAAFontSettings"));
 1836               }
 1837               if (systemAAFonts != null) {
 1838                   useSystemAAFontSettings =
 1839                       Boolean.valueOf(systemAAFonts).booleanValue();
 1840                   /* If it is anything other than "true", then it may be
 1841                    * a hint name , or it may be "off, "default", etc.
 1842                    */
 1843                   if (!useSystemAAFontSettings) {
 1844                       desktopFontHints = getDesktopAAHintsByName(systemAAFonts);
 1845                   }
 1846               }
 1847               /* If its still true, apply the extra condition */
 1848               if (useSystemAAFontSettings) {
 1849                    useSystemAAFontSettings = lastExtraCondition;
 1850               }
 1851               checkedSystemAAFontSettings = true;
 1852           }
 1853           return useSystemAAFontSettings;
 1854       }
 1855   
 1856       /* A variable defined for the convenience of JDK code */
 1857       public static final String DESKTOPFONTHINTS = "awt.font.desktophints";
 1858   
 1859       /* Overridden by subclasses to return platform/desktop specific values */
 1860       protected RenderingHints getDesktopAAHints() {
 1861           return null;
 1862       }
 1863   
 1864       /* Subclass desktop property loading methods call this which
 1865        * in turn calls the appropriate subclass implementation of
 1866        * getDesktopAAHints() when system settings are being used.
 1867        * Its public rather than protected because subclasses may delegate
 1868        * to a helper class.
 1869        */
 1870       public static RenderingHints getDesktopFontHints() {
 1871           if (useSystemAAFontSettings()) {
 1872                Toolkit tk = Toolkit.getDefaultToolkit();
 1873                if (tk instanceof SunToolkit) {
 1874                    Object map = ((SunToolkit)tk).getDesktopAAHints();
 1875                    return (RenderingHints)map;
 1876                } else { /* Headless Toolkit */
 1877                    return null;
 1878                }
 1879           } else if (desktopFontHints != null) {
 1880               /* cloning not necessary as the return value is cloned later, but
 1881                * its harmless.
 1882                */
 1883               return (RenderingHints)(desktopFontHints.clone());
 1884           } else {
 1885               return null;
 1886           }
 1887       }
 1888   
 1889   
 1890       public abstract boolean isDesktopSupported();
 1891   
 1892       /*
 1893        * consumeNextKeyTyped() method is not currently used,
 1894        * however Swing could use it in the future.
 1895        */
 1896       private static Method consumeNextKeyTypedMethod = null;
 1897       public static synchronized void consumeNextKeyTyped(KeyEvent keyEvent) {
 1898           if (consumeNextKeyTypedMethod == null) {
 1899               consumeNextKeyTypedMethod = getMethod(DefaultKeyboardFocusManager.class,
 1900                                                     "consumeNextKeyTyped",
 1901                                                     new Class[] {KeyEvent.class});
 1902           }
 1903           try {
 1904               consumeNextKeyTypedMethod.invoke(KeyboardFocusManager.getCurrentKeyboardFocusManager(),
 1905                                                keyEvent);
 1906           } catch (IllegalAccessException iae) {
 1907               iae.printStackTrace();
 1908           } catch (InvocationTargetException ite) {
 1909               ite.printStackTrace();
 1910           }
 1911       }
 1912   
 1913       protected static void dumpPeers(final PlatformLogger aLog) {
 1914           AWTAutoShutdown.getInstance().dumpPeers(aLog);
 1915       }
 1916   
 1917       /**
 1918        * Returns the <code>Window</code> ancestor of the component <code>comp</code>.
 1919        * @return Window ancestor of the component or component by itself if it is Window;
 1920        *         null, if component is not a part of window hierarchy
 1921        */
 1922       public static Window getContainingWindow(Component comp) {
 1923           while (comp != null && !(comp instanceof Window)) {
 1924               comp = comp.getParent();
 1925           }
 1926           return (Window)comp;
 1927       }
 1928   
 1929       /**
 1930        * Returns the value of the system property indicated by the specified key.
 1931        */
 1932       public static String getSystemProperty(final String key) {
 1933           return (String)AccessController.doPrivileged(new PrivilegedAction() {
 1934                   public Object run() {
 1935                       return System.getProperty(key);
 1936                   }
 1937               });
 1938       }
 1939   
 1940       /**
 1941        * Returns the boolean value of the system property indicated by the specified key.
 1942        */
 1943       protected static Boolean getBooleanSystemProperty(String key) {
 1944           return Boolean.valueOf(AccessController.
 1945                      doPrivileged(new GetBooleanAction(key)));
 1946       }
 1947   
 1948       private static Boolean sunAwtDisableMixing = null;
 1949   
 1950       /**
 1951        * Returns the value of "sun.awt.disableMixing" property. Default
 1952        * value is {@code false}.
 1953        */
 1954       public synchronized static boolean getSunAwtDisableMixing() {
 1955           if (sunAwtDisableMixing == null) {
 1956               sunAwtDisableMixing = getBooleanSystemProperty("sun.awt.disableMixing");
 1957           }
 1958           return sunAwtDisableMixing.booleanValue();
 1959       }
 1960   
 1961       /**
 1962        * Returns true if the native GTK libraries are available.  The
 1963        * default implementation returns false, but UNIXToolkit overrides this
 1964        * method to provide a more specific answer.
 1965        */
 1966       public boolean isNativeGTKAvailable() {
 1967           return false;
 1968       }
 1969   
 1970       // Cosntant alpha
 1971       public boolean isWindowOpacitySupported() {
 1972           return false;
 1973       }
 1974   
 1975       // Shaping
 1976       public boolean isWindowShapingSupported() {
 1977           return false;
 1978       }
 1979   
 1980       // Per-pixel alpha
 1981       public boolean isWindowTranslucencySupported() {
 1982           return false;
 1983       }
 1984   
 1985       public boolean isTranslucencyCapable(GraphicsConfiguration gc) {
 1986           return false;
 1987       }
 1988   
 1989       /**
 1990        * Returns whether or not a containing top level window for the passed
 1991        * component is
 1992        * {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT PERPIXEL_TRANSLUCENT}.
 1993        *
 1994        * @param c a Component which toplevel's to check
 1995        * @return {@code true}  if the passed component is not null and has a
 1996        * containing toplevel window which is opaque (so per-pixel translucency
 1997        * is not enabled), {@code false} otherwise
 1998        * @see GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
 1999        */
 2000       public static boolean isContainingTopLevelOpaque(Component c) {
 2001           Window w = getContainingWindow(c);
 2002           return w != null && w.isOpaque();
 2003       }
 2004   
 2005       /**
 2006        * Returns whether or not a containing top level window for the passed
 2007        * component is
 2008        * {@link GraphicsDevice.WindowTranslucency#TRANSLUCENT TRANSLUCENT}.
 2009        *
 2010        * @param c a Component which toplevel's to check
 2011        * @return {@code true} if the passed component is not null and has a
 2012        * containing toplevel window which has opacity less than
 2013        * 1.0f (which means that it is translucent), {@code false} otherwise
 2014        * @see GraphicsDevice.WindowTranslucency#TRANSLUCENT
 2015        */
 2016       public static boolean isContainingTopLevelTranslucent(Component c) {
 2017           Window w = getContainingWindow(c);
 2018           return w != null && ((Window)w).getOpacity() < 1.0f;
 2019       }
 2020   
 2021       /**
 2022        * Returns whether the native system requires using the peer.updateWindow()
 2023        * method to update the contents of a non-opaque window, or if usual
 2024        * painting procedures are sufficient. The default return value covers
 2025        * the X11 systems. On MS Windows this method is overriden in WToolkit
 2026        * to return true.
 2027        */
 2028       public boolean needUpdateWindow() {
 2029           return false;
 2030       }
 2031   
 2032       /**
 2033        * Descendants of the SunToolkit should override and put their own logic here.
 2034        */
 2035       public int getNumberOfButtons(){
 2036           return 3;
 2037       }
 2038   
 2039       /**
 2040        * Checks that the given object implements/extends the given
 2041        * interface/class.
 2042        *
 2043        * Note that using the instanceof operator causes a class to be loaded.
 2044        * Using this method doesn't load a class and it can be used instead of
 2045        * the instanceof operator for performance reasons.
 2046        *
 2047        * @param obj Object to be checked
 2048        * @param type The name of the interface/class. Must be
 2049        * fully-qualified interface/class name.
 2050        * @return true, if this object implements/extends the given
 2051        *         interface/class, false, otherwise, or if obj or type is null
 2052        */
 2053       public static boolean isInstanceOf(Object obj, String type) {
 2054           if (obj == null) return false;
 2055           if (type == null) return false;
 2056   
 2057           return isInstanceOf(obj.getClass(), type);
 2058       }
 2059   
 2060       private static boolean isInstanceOf(Class cls, String type) {
 2061           if (cls == null) return false;
 2062   
 2063           if (cls.getName().equals(type)) {
 2064               return true;
 2065           }
 2066   
 2067           for (Class c : cls.getInterfaces()) {
 2068               if (c.getName().equals(type)) {
 2069                   return true;
 2070               }
 2071           }
 2072           return isInstanceOf(cls.getSuperclass(), type);
 2073       }
 2074   
 2075       ///////////////////////////////////////////////////////////////////////////
 2076       //
 2077       // The following methods help set and identify whether a particular
 2078       // AWTEvent object was produced by the system or by user code. As of this
 2079       // writing the only consumer is the Java Plug-In, although this information
 2080       // could be useful to more clients and probably should be formalized in
 2081       // the public API.
 2082       //
 2083       ///////////////////////////////////////////////////////////////////////////
 2084   
 2085       public static void setSystemGenerated(AWTEvent e) {
 2086           AWTAccessor.getAWTEventAccessor().setSystemGenerated(e);
 2087       }
 2088   
 2089       public static boolean isSystemGenerated(AWTEvent e) {
 2090           return AWTAccessor.getAWTEventAccessor().isSystemGenerated(e);
 2091       }
 2092   
 2093   } // class SunToolkit
 2094   
 2095   
 2096   /*
 2097    * PostEventQueue is a Thread that runs in the same AppContext as the
 2098    * Java EventQueue.  It is a queue of AWTEvents to be posted to the
 2099    * Java EventQueue.  The toolkit Thread (AWT-Windows/AWT-Motif) posts
 2100    * events to this queue, which then calls EventQueue.postEvent().
 2101    *
 2102    * We do this because EventQueue.postEvent() may be overridden by client
 2103    * code, and we mustn't ever call client code from the toolkit thread.
 2104    */
 2105   class PostEventQueue {
 2106       private EventQueueItem queueHead = null;
 2107       private EventQueueItem queueTail = null;
 2108       private final EventQueue eventQueue;
 2109   
 2110       PostEventQueue(EventQueue eq) {
 2111           eventQueue = eq;
 2112       }
 2113   
 2114       public synchronized boolean noEvents() {
 2115           return queueHead == null;
 2116       }
 2117   
 2118       /*
 2119        * Continually post pending AWTEvents to the Java EventQueue. The method
 2120        * is synchronized to ensure the flush is completed before a new event
 2121        * can be posted to this queue.
 2122        */
 2123       public synchronized void flush() {
 2124           EventQueueItem tempQueue = queueHead;
 2125           queueHead = queueTail = null;
 2126           while (tempQueue != null) {
 2127               eventQueue.postEvent(tempQueue.event);
 2128               tempQueue = tempQueue.next;
 2129           }
 2130       }
 2131   
 2132       /*
 2133        * Enqueue an AWTEvent to be posted to the Java EventQueue.
 2134        */
 2135       void postEvent(AWTEvent event) {
 2136           EventQueueItem item = new EventQueueItem(event);
 2137   
 2138           synchronized (this) {
 2139               if (queueHead == null) {
 2140                   queueHead = queueTail = item;
 2141               } else {
 2142                   queueTail.next = item;
 2143                   queueTail = item;
 2144               }
 2145           }
 2146           SunToolkit.wakeupEventQueue(eventQueue, event.getSource() == AWTAutoShutdown.getInstance());
 2147       }
 2148   } // class PostEventQueue

Save This Page
Home » openjdk-7 » sun » awt » [javadoc | source]