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