~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/sun/awt/SunToolkit.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

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