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