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.
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.
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).
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.
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
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;
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;
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;
63
public abstract class SunToolkit extends Toolkit
64
implements WindowClosingSupport, WindowClosingListener,
65
ComponentFactory, InputMethodSupport, KeyboardFocusManagerPeerProvider {
67
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.SunToolkit");
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.
74
public static final int GRAB_EVENT_MASK = 0x80000000;
76
private static Method wakeupMethod;
77
/* The key to put()/get() the PostEventQueue into/from the AppContext.
79
private static final String POST_EVENT_QUEUE_KEY = "PostEventQueue";
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.
86
protected static int numberOfButtons = 0;
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.
98
public final static int MAX_BUTTONS_SUPPORTED = 20;
100
private static void initEQ(AppContext appContext) {
101
EventQueue eventQueue;
103
String eqName = System.getProperty("AWT.EventQueueClass",
104
"java.awt.EventQueue");
107
eventQueue = (EventQueue)Class.forName(eqName).newInstance();
108
} catch (Exception e) {
110
System.err.println("Failed loading " + eqName + ": " + e);
111
eventQueue = new EventQueue();
113
appContext.put(AppContext.EVENT_QUEUE_KEY, eventQueue);
115
PostEventQueue postEventQueue = new PostEventQueue(eventQueue);
116
appContext.put(POST_EVENT_QUEUE_KEY, postEventQueue);
119
public SunToolkit() {
120
// 7122796: Always create an EQ for the main AppContext
121
initEQ(AppContext.getMainAppContext());
124
public boolean useBufferPerWindow() {
128
public abstract WindowPeer createWindow(Window target)
129
throws HeadlessException;
131
public abstract FramePeer createFrame(Frame target)
132
throws HeadlessException;
134
public abstract DialogPeer createDialog(Dialog target)
135
throws HeadlessException;
137
public abstract ButtonPeer createButton(Button target)
138
throws HeadlessException;
140
public abstract TextFieldPeer createTextField(TextField target)
141
throws HeadlessException;
143
public abstract ChoicePeer createChoice(Choice target)
144
throws HeadlessException;
146
public abstract LabelPeer createLabel(Label target)
147
throws HeadlessException;
149
public abstract ListPeer createList(java.awt.List target)
150
throws HeadlessException;
152
public abstract CheckboxPeer createCheckbox(Checkbox target)
153
throws HeadlessException;
155
public abstract ScrollbarPeer createScrollbar(Scrollbar target)
156
throws HeadlessException;
158
public abstract ScrollPanePeer createScrollPane(ScrollPane target)
159
throws HeadlessException;
161
public abstract TextAreaPeer createTextArea(TextArea target)
162
throws HeadlessException;
164
public abstract FileDialogPeer createFileDialog(FileDialog target)
165
throws HeadlessException;
167
public abstract MenuBarPeer createMenuBar(MenuBar target)
168
throws HeadlessException;
170
public abstract MenuPeer createMenu(Menu target)
171
throws HeadlessException;
173
public abstract PopupMenuPeer createPopupMenu(PopupMenu target)
174
throws HeadlessException;
176
public abstract MenuItemPeer createMenuItem(MenuItem target)
177
throws HeadlessException;
179
public abstract CheckboxMenuItemPeer createCheckboxMenuItem(
180
CheckboxMenuItem target)
181
throws HeadlessException;
183
public abstract DragSourceContextPeer createDragSourceContextPeer(
184
DragGestureEvent dge)
185
throws InvalidDnDOperationException;
187
public abstract TrayIconPeer createTrayIcon(TrayIcon target)
188
throws HeadlessException, AWTException;
190
public abstract SystemTrayPeer createSystemTray(SystemTray target);
192
public abstract boolean isTraySupported();
194
public abstract FontPeer getFontPeer(String name, int style);
196
public abstract RobotPeer createRobot(Robot target, GraphicsDevice screen)
199
public abstract KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
200
throws HeadlessException;
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.
211
* Note: The following methods (awtLock(), awtUnlock(), etc) should be
213
* synchronized (getAWTLock()) {
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.
222
* private void doStuffWithXlib() {
223
* assert !SunToolkit.isAWTLockHeldByCurrentThread();
224
* SunToolkit.awtLock();
227
* XlibWrapper.XDoStuff();
229
* SunToolkit.awtUnlock();
234
private static final ReentrantLock AWT_LOCK = new ReentrantLock();
235
private static final Condition AWT_LOCK_COND = AWT_LOCK.newCondition();
237
public static final void awtLock() {
241
public static final boolean awtTryLock() {
242
return AWT_LOCK.tryLock();
245
public static final void awtUnlock() {
249
public static final void awtLockWait()
250
throws InterruptedException
252
AWT_LOCK_COND.await();
255
public static final void awtLockWait(long timeout)
256
throws InterruptedException
258
AWT_LOCK_COND.await(timeout, TimeUnit.MILLISECONDS);
261
public static final void awtLockNotify() {
262
AWT_LOCK_COND.signal();
265
public static final void awtLockNotifyAll() {
266
AWT_LOCK_COND.signalAll();
269
public static final boolean isAWTLockHeldByCurrentThread() {
270
return AWT_LOCK.isHeldByCurrentThread();
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.
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);
290
public static Field getField(final Class klass, final String fieldName) {
291
return AccessController.doPrivileged(new PrivilegedAction<Field>() {
294
Field field = klass.getDeclaredField(fieldName);
295
assert (field != null);
296
field.setAccessible(true);
298
} catch (SecurityException e) {
300
} catch (NoSuchFieldException e) {
308
static void wakeupEventQueue(EventQueue q, boolean isShutdown){
309
if (wakeupMethod == null){
310
wakeupMethod = (Method)AccessController.doPrivileged(new PrivilegedAction(){
313
Method method = EventQueue.class.getDeclaredMethod("wakeup",new Class [] {Boolean.TYPE} );
314
if (method != null) {
315
method.setAccessible(true);
318
} catch (NoSuchMethodException e) {
320
} catch (SecurityException e) {
328
if (wakeupMethod != null){
329
wakeupMethod.invoke(q, new Object[]{Boolean.valueOf(isShutdown)});
331
} catch (InvocationTargetException e){
333
} catch (IllegalAccessException e) {
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
346
protected static Object targetToPeer(Object target) {
347
if (target != null && !GraphicsEnvironment.isHeadless()) {
348
return AWTAutoShutdown.getInstance().getPeer(target);
353
protected static void targetCreatedPeer(Object target, Object peer) {
354
if (target != null && peer != null &&
355
!GraphicsEnvironment.isHeadless())
357
AWTAutoShutdown.getInstance().registerPeer(target, peer);
361
protected static void targetDisposedPeer(Object target, Object peer) {
362
if (target != null && peer != null &&
363
!GraphicsEnvironment.isHeadless())
365
AWTAutoShutdown.getInstance().unregisterPeer(target, peer);
369
// Maps from non-Component/MenuComponent to AppContext.
370
// WeakHashMap<Component,AppContext>
371
private static final Map appContextMap =
372
Collections.synchronizedMap(new WeakHashMap());
375
* Sets the appContext field of target. If target is not a Component or
376
* MenuComponent, this returns false.
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);
393
* Returns the appContext field for target. If target is not a
394
* Component or MenuComponent this returns null.
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);
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.
414
public static AppContext targetToAppContext(Object target) {
415
if (target == null || GraphicsEnvironment.isHeadless()) {
418
AppContext context = getAppContext(target);
419
if (context == null) {
420
// target is not a Component/MenuComponent, try the
422
context = (AppContext)appContextMap.get(target);
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.
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.
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.
447
* @param w window for which the lightweight focus request status
449
* @param status the value of lightweight focus request status
452
public static void setLWRequestStatus(Window changed,boolean status){
453
AWTAccessor.getWindowAccessor().setLWRequestStatus(changed, status);
456
public static void checkAndSetPolicy(Container cont) {
457
FocusTraversalPolicy defaultPolicy = KeyboardFocusManager.
458
getCurrentKeyboardFocusManager().
459
getDefaultFocusTraversalPolicy();
461
cont.setFocusTraversalPolicy(defaultPolicy);
464
private static FocusTraversalPolicy createLayoutPolicy() {
465
FocusTraversalPolicy policy = null;
467
Class layoutPolicyClass =
468
Class.forName("javax.swing.LayoutFocusTraversalPolicy");
469
policy = (FocusTraversalPolicy) layoutPolicyClass.newInstance();
471
catch (ClassNotFoundException e) {
474
catch (InstantiationException e) {
477
catch (IllegalAccessException e) {
485
* Insert a mapping from target to AppContext, for later retrieval
486
* via targetToAppContext() above.
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
493
appContextMap.put(target, appContext);
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.
505
public static void postEvent(AppContext appContext, AWTEvent event) {
507
throw new NullPointerException();
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);
519
PostEventQueue postEventQueue =
520
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
521
if (postEventQueue != null) {
522
postEventQueue.postEvent(event);
527
* Post AWTEvent of high priority.
529
public static void postPriorityEvent(final AWTEvent e) {
530
PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() {
532
AWTAccessor.getAWTEventAccessor().setPosted(e);
533
((Component)e.getSource()).dispatchEvent(e);
535
}, PeerEvent.ULTIMATE_PRIORITY_EVENT);
536
postEvent(targetToAppContext(e.getSource()), pe);
539
protected static final Lock flushLock = new ReentrantLock();
540
private static boolean isFlushingPendingEvents = false;
543
* Flush any pending events which haven't been posted to the AWT
546
public static void flushPendingEvents() {
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();
560
isFlushingPendingEvents = false;
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();
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.
581
public static void executeOnEventHandlerThread(Object target,
583
executeOnEventHandlerThread(new PeerEvent(target, runnable, PeerEvent.PRIORITY_EVENT));
587
* Fixed 5064013: the InvocationEvent time should be equals
588
* the time of the ActionEvent
590
public static void executeOnEventHandlerThread(Object target,
593
executeOnEventHandlerThread(new PeerEvent(target, runnable, PeerEvent.PRIORITY_EVENT){
594
public long getWhen(){
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.
605
public static void executeOnEventHandlerThread(PeerEvent peerEvent) {
606
postEvent(targetToAppContext(peerEvent.getSource()), peerEvent);
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
617
public static void invokeLaterOnAppContext(
618
AppContext appContext, Runnable dispatcher)
620
postEvent(appContext,
621
new PeerEvent(Toolkit.getDefaultToolkit(), dispatcher,
622
PeerEvent.PRIORITY_EVENT));
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
630
public static void executeOnEDTAndWait(Object target, Runnable runnable)
631
throws InterruptedException, InvocationTargetException
633
if (EventQueue.isDispatchThread()) {
634
throw new Error("Cannot call executeOnEDTAndWait from any event dispatcher thread");
637
class AWTInvocationLock {}
638
Object lock = new AWTInvocationLock();
640
PeerEvent event = new PeerEvent(target, runnable, lock, true, PeerEvent.PRIORITY_EVENT);
642
synchronized (lock) {
643
executeOnEventHandlerThread(event);
644
while(!event.isDispatched()) {
649
Throwable eventThrowable = event.getThrowable();
650
if (eventThrowable != null) {
651
throw new InvocationTargetException(eventThrowable);
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.
661
public static boolean isDispatchThreadForAppContext(Object target) {
662
AppContext appContext = targetToAppContext(target);
663
EventQueue eq = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
665
AWTAccessor.EventQueueAccessor accessor = AWTAccessor.getEventQueueAccessor();
666
return accessor.isDispatchThreadImpl(eq);
669
public Dimension getScreenSize() {
670
return new Dimension(getScreenWidth(), getScreenHeight());
672
protected abstract int getScreenWidth();
673
protected abstract int getScreenHeight();
675
public String[] getFontList() {
676
String[] hardwiredFontList = {
677
Font.DIALOG, Font.SANS_SERIF, Font.SERIF, Font.MONOSPACED,
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"
684
return hardwiredFontList;
687
public PanelPeer createPanel(Panel target) {
688
return (PanelPeer)createComponent(target);
691
public CanvasPeer createCanvas(Canvas target) {
692
return (CanvasPeer)createComponent(target);
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.
702
public void disableBackgroundErase(Canvas canvas) {
703
disableBackgroundEraseImpl(canvas);
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.
715
public void disableBackgroundErase(Component component) {
716
disableBackgroundEraseImpl(component);
719
private void disableBackgroundEraseImpl(Component component) {
720
AWTAccessor.getComponentAccessor().setBackgroundEraseDisabled(component, true);
724
* Returns the value of "sun.awt.noerasebackground" property. Default
725
* value is {@code false}.
727
public static boolean getSunAwtNoerasebackground() {
728
return AccessController.doPrivileged(new GetBooleanAction("sun.awt.noerasebackground"));
732
* Returns the value of "sun.awt.erasebackgroundonresize" property. Default
733
* value is {@code false}.
735
public static boolean getSunAwtErasebackgroundonresize() {
736
return AccessController.doPrivileged(new GetBooleanAction("sun.awt.erasebackgroundonresize"));
739
public Image createImage(ImageProducer producer) {
740
return new ToolkitImage(producer);
743
public int checkImage(Image img, int w, int h, ImageObserver o) {
744
if (!(img instanceof ToolkitImage)) {
745
return ImageObserver.ALLBITS;
748
ToolkitImage tkimg = (ToolkitImage)img;
750
if (w == 0 || h == 0) {
751
repbits = ImageObserver.ALLBITS;
753
repbits = tkimg.getImageRep().check(o);
755
return tkimg.check(o) | repbits;
758
public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
759
if (w == 0 || h == 0) {
763
// Must be a ToolkitImage
764
if (!(img instanceof ToolkitImage)) {
768
ToolkitImage tkimg = (ToolkitImage)img;
769
if (tkimg.hasError()) {
771
o.imageUpdate(img, ImageObserver.ERROR|ImageObserver.ABORT,
776
ImageRepresentation ir = tkimg.getImageRep();
777
return ir.prepare(o);
781
* Scans {@code imageList} for best-looking image of specified dimensions.
782
* Image can be scaled and/or padded with transparency.
784
public static BufferedImage getScaledIconImage(java.util.List<Image> imageList, int width, int height) {
785
if (width == 0 || height == 0) {
788
Image bestImage = null;
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.
801
if (log.isLoggable(PlatformLogger.FINER)) {
802
log.finer("SunToolkit.getScaledIconImage: " +
803
"Skipping the image passed into Java because it's null.");
807
if (im instanceof ToolkitImage) {
808
ImageRepresentation ir = ((ToolkitImage)im).getImageRep();
809
ir.reconstruct(ImageObserver.ALLBITS);
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.");
823
if (iw > 0 && ih > 0) {
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
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) {
845
} else if (scaleFactor >= 0.75) {
851
} else if (scaleFactor >= 0.6666) {
853
scaleFactor = 0.6666;
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;
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;
877
if (similarity == 0) break;
880
if (bestImage == null) {
881
//No images were found, possibly all are broken
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);
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);
900
g.drawImage(bestImage, x, y, bestWidth, bestHeight, null);
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.");
916
Raster raster = bimage.getRaster();
917
DataBuffer buffer = raster.getDataBuffer();
918
return (DataBufferInt)buffer;
921
protected EventQueue getSystemEventQueueImpl() {
922
return getSystemEventQueueImplPP();
925
// Package private implementation
926
static EventQueue getSystemEventQueueImplPP() {
927
return getSystemEventQueueImplPP(AppContext.getAppContext());
930
public static EventQueue getSystemEventQueueImplPP(AppContext appContext) {
931
EventQueue theEventQueue =
932
(EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
933
return theEventQueue;
937
* Give native peers the ability to query the native container
938
* given a native component (eg the direct parent may be lightweight).
940
public static Container getNativeContainer(Component c) {
941
return Toolkit.getNativeContainer(c);
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.
949
public static Component getHeavyweightComponent(Component c) {
950
while (c != null && AWTAccessor.getComponentAccessor().isLightweight(c)) {
951
c = AWTAccessor.getComponentAccessor().getParent(c);
957
* Returns key modifiers used by Swing to set up a focus accelerator key stroke.
959
public int getFocusAcceleratorKeyMask() {
960
return InputEvent.ALT_MASK;
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)
969
public boolean isPrintableCharacterModifiersMask(int mods) {
970
return ((mods & InputEvent.ALT_MASK) == (mods & InputEvent.CTRL_MASK));
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.
978
public boolean canPopupOverlapTaskBar() {
979
boolean result = true;
981
SecurityManager sm = System.getSecurityManager();
984
SecurityConstants.AWT.SET_WINDOW_ALWAYS_ON_TOP_PERMISSION);
986
} catch (SecurityException se) {
987
// There is no permission to show popups over the task bar
994
* Returns whether enableInputMethods should be set to true for peered
995
* TextComponent instances on this platform. False by default.
997
public boolean enableInputMethodsForTextComponent() {
1001
private static Locale startupLocale = null;
1004
* Returns the locale in which the runtime was started.
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('_');
1018
country = region.substring(0, i);
1019
variant = region.substring(i + 1);
1025
country = (String) AccessController.doPrivileged(
1026
new GetPropertyAction("user.country", ""));
1027
variant = (String) AccessController.doPrivileged(
1028
new GetPropertyAction("user.variant", ""));
1030
startupLocale = new Locale(language, country, variant);
1032
return startupLocale;
1036
* Returns the default keyboard locale of the underlying operating system
1038
public Locale getDefaultKeyboardLocale() {
1039
return getStartupLocale();
1042
private static String dataTransfererClassName = null;
1044
protected static void setDataTransfererClassName(String className) {
1045
dataTransfererClassName = className;
1048
public static String getDataTransfererClassName() {
1049
if (dataTransfererClassName == null) {
1050
Toolkit.getDefaultToolkit(); // transferer set during toolkit init
1052
return dataTransfererClassName;
1055
// Support for window closing event notifications
1056
private transient WindowClosingListener windowClosingListener = null;
1058
* @see sun.awt.WindowClosingSupport#getWindowClosingListener
1060
public WindowClosingListener getWindowClosingListener() {
1061
return windowClosingListener;
1064
* @see sun.awt.WindowClosingSupport#setWindowClosingListener
1066
public void setWindowClosingListener(WindowClosingListener wcl) {
1067
windowClosingListener = wcl;
1071
* @see sun.awt.WindowClosingListener#windowClosingNotify
1073
public RuntimeException windowClosingNotify(WindowEvent event) {
1074
if (windowClosingListener != null) {
1075
return windowClosingListener.windowClosingNotify(event);
1081
* @see sun.awt.WindowClosingListener#windowClosingDelivered
1083
public RuntimeException windowClosingDelivered(WindowEvent event) {
1084
if (windowClosingListener != null) {
1085
return windowClosingListener.windowClosingDelivered(event);
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
1098
public static boolean needsXEmbed() {
1099
String noxembed = (String) AccessController.
1100
doPrivileged(new GetPropertyAction("sun.awt.noxembed", "false"));
1101
if ("true".equals(noxembed)) {
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();
1111
// Non-SunToolkit doubtly might support XEmbed
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
1121
protected boolean needsXEmbedImpl() {
1125
private static Dialog.ModalExclusionType DEFAULT_MODAL_EXCLUSION_TYPE = null;
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.
1132
protected final boolean isXEmbedServerRequested() {
1133
return AccessController.doPrivileged(new GetBooleanAction("sun.awt.xembedserver"));
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.
1141
* @return true if modal exclusion is supported by the toolkit, false otherwise
1143
* @see sun.awt.SunToolkit#setModalExcluded(java.awt.Window)
1144
* @see sun.awt.SunToolkit#isModalExcluded(java.awt.Window)
1148
public static boolean isModalExcludedSupported()
1150
Toolkit tk = Toolkit.getDefaultToolkit();
1151
return tk.isModalExclusionTypeSupported(DEFAULT_MODAL_EXCLUSION_TYPE);
1154
* Default implementation for isModalExcludedSupportedImpl(), returns false.
1156
* @see sun.awt.windows.WToolkit#isModalExcludeSupportedImpl
1157
* @see sun.awt.X11.XToolkit#isModalExcludeSupportedImpl
1161
protected boolean isModalExcludedSupportedImpl()
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)
1182
public static void setModalExcluded(Window window)
1184
if (DEFAULT_MODAL_EXCLUSION_TYPE == null) {
1185
DEFAULT_MODAL_EXCLUSION_TYPE = Dialog.ModalExclusionType.APPLICATION_EXCLUDE;
1187
window.setModalExclusionType(DEFAULT_MODAL_EXCLUSION_TYPE);
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.
1195
* @param window Window to test for modal exclusion
1197
* @return true if the window is modal excluded, false otherwise. If
1198
* the modal exclusion isn't supported by the current Toolkit, false
1201
* @see sun.awt.SunToolkit#isModalExcludedSupported
1202
* @see sun.awt.SunToolkit#setModalExcluded(java.awt.Window)
1206
public static boolean isModalExcluded(Window window)
1208
if (DEFAULT_MODAL_EXCLUSION_TYPE == null) {
1209
DEFAULT_MODAL_EXCLUSION_TYPE = Dialog.ModalExclusionType.APPLICATION_EXCLUDE;
1211
return window.getModalExclusionType().compareTo(DEFAULT_MODAL_EXCLUSION_TYPE) >= 0;
1215
* Overridden in XToolkit and WToolkit
1217
public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
1218
return (modalityType == Dialog.ModalityType.MODELESS) ||
1219
(modalityType == Dialog.ModalityType.APPLICATION_MODAL);
1223
* Overridden in XToolkit and WToolkit
1225
public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
1226
return (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE);
1229
///////////////////////////////////////////////////////////////////////////
1231
// The following is used by the Java Plug-in to coordinate dialog modality
1232
// between containing applications (browsers, ActiveX containers etc) and
1235
///////////////////////////////////////////////////////////////////////////
1237
private ModalityListenerList modalityListeners = new ModalityListenerList();
1239
public void addModalityListener(ModalityListener listener) {
1240
modalityListeners.add(listener);
1243
public void removeModalityListener(ModalityListener listener) {
1244
modalityListeners.remove(listener);
1247
public void notifyModalityPushed(Dialog dialog) {
1248
notifyModalityChange(ModalityEvent.MODALITY_PUSHED, dialog);
1251
public void notifyModalityPopped(Dialog dialog) {
1252
notifyModalityChange(ModalityEvent.MODALITY_POPPED, dialog);
1255
final void notifyModalityChange(int id, Dialog source) {
1256
ModalityEvent ev = new ModalityEvent(source, modalityListeners, id);
1260
static class ModalityListenerList implements ModalityListener {
1262
Vector<ModalityListener> listeners = new Vector<ModalityListener>();
1264
void add(ModalityListener listener) {
1265
listeners.addElement(listener);
1268
void remove(ModalityListener listener) {
1269
listeners.removeElement(listener);
1272
public void modalityPushed(ModalityEvent ev) {
1273
Iterator<ModalityListener> it = listeners.iterator();
1274
while (it.hasNext()) {
1275
it.next().modalityPushed(ev);
1279
public void modalityPopped(ModalityEvent ev) {
1280
Iterator<ModalityListener> it = listeners.iterator();
1281
while (it.hasNext()) {
1282
it.next().modalityPopped(ev);
1285
} // end of class ModalityListenerList
1287
///////////////////////////////////////////////////////////////////////////
1289
///////////////////////////////////////////////////////////////////////////
1291
public static boolean isLightweightOrUnknown(Component comp) {
1292
if (comp.isLightweight()
1293
|| !(getDefaultToolkit() instanceof SunToolkit))
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);
1311
public static Method getMethod(final Class clz, final String methodName, final Class[] params) {
1314
res = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
1315
public Method run() throws Exception {
1316
Method m = clz.getDeclaredMethod(methodName, params);
1317
m.setAccessible(true);
1321
} catch (PrivilegedActionException ex) {
1322
ex.printStackTrace();
1327
public static class OperationTimedOut extends RuntimeException {
1328
public OperationTimedOut(String msg) {
1331
public OperationTimedOut() {
1334
public static class InfiniteLoop extends RuntimeException {
1337
public static class IllegalThreadException extends RuntimeException {
1338
public IllegalThreadException(String msg) {
1341
public IllegalThreadException() {
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;
1351
* Parameterless version of realsync which uses default timout (see DEFAUL_WAIT_TIME).
1353
public void realSync() throws OperationTimedOut, InfiniteLoop {
1354
realSync(DEFAULT_WAIT_TIME);
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.
1367
* <p> This method allows to write tests without explicit timeouts
1368
* or wait for some event. Example:
1371
* f.setVisible(true);
1372
* ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
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.
1379
* <p> Another example:
1382
* ((SunToolkit)Toolkit.getDefaultToolkit()).realSync();
1385
* <p> After realSync, <code>b</code> will be focus owner.
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.
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.
1400
* @param timeout the maximum time to wait in milliseconds, negative means "forever".
1402
public void realSync(final long timeout) throws OperationTimedOut, InfiniteLoop
1404
if (EventQueue.isDispatchThread()) {
1405
throw new IllegalThreadException("The SunToolkit.realSync() method cannot be used on the event dispatch thread (EDT).");
1409
// Let's do sync first
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
1418
while (iters < MIN_ITERS) {
1419
syncNativeQueue(timeout);
1422
while (syncNativeQueue(timeout) && iters < MAX_ITERS) {
1425
if (iters >= MAX_ITERS) {
1426
throw new InfiniteLoop();
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.
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
1437
while (iters < MIN_ITERS) {
1438
waitForIdle(timeout);
1441
while (waitForIdle(timeout) && iters < MAX_ITERS) {
1444
if (iters >= MAX_ITERS) {
1445
throw new InfiniteLoop();
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);
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.
1463
protected abstract boolean syncNativeQueue(final long timeout);
1465
private boolean eventDispatched = false;
1466
private boolean queueEmpty = false;
1467
private final Object waitLock = "Wait Lock";
1469
static Method eqNoEvents;
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);
1479
return (Boolean)eqNoEvents.invoke(queue);
1480
} catch (Exception e) {
1481
e.printStackTrace();
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.
1493
protected final boolean waitForIdle(final long timeout) {
1494
flushPendingEvents();
1495
boolean queueWasEmpty = isEQEmpty();
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.
1508
while (iters < MIN_ITERS) {
1509
syncNativeQueue(timeout);
1512
while (syncNativeQueue(timeout) && iters < MAX_ITERS) {
1515
flushPendingEvents();
1517
synchronized(waitLock) {
1518
queueEmpty = isEQEmpty();
1519
eventDispatched = true;
1520
waitLock.notifyAll();
1525
while (!eventDispatched) {
1528
} catch (InterruptedException ie) {
1534
Thread.sleep(MINIMAL_EDELAY);
1535
} catch (InterruptedException ie) {
1536
throw new RuntimeException("Interrupted");
1539
flushPendingEvents();
1541
// Lock to force write-cache flush for queueEmpty.
1542
synchronized (waitLock) {
1543
return !(queueEmpty && isEQEmpty() && queueWasEmpty);
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
1559
public abstract void grab(Window w);
1562
* Forces ungrab. No event will be sent.
1564
public abstract void ungrab(Window w);
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
1573
public static native void closeSplashScreen();
1575
/* The following methods and variables are to support retrieving
1576
* desktop text anti-aliasing settings
1579
/* Need an instance method because setDesktopProperty(..) is protected. */
1580
private void fireDesktopFontPropertyChanges() {
1581
setDesktopProperty(SunToolkit.DESKTOPFONTHINTS,
1582
SunToolkit.getDesktopFontHints());
1585
private static boolean checkedSystemAAFontSettings;
1586
private static boolean useSystemAAFontSettings;
1587
private static boolean lastExtraCondition = true;
1588
private static RenderingHints desktopFontHints;
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.
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
1620
* We'll force re-evaluation instead of replicating the
1621
* logic, then notify any listeners of any change.
1623
checkedSystemAAFontSettings = false;
1624
Toolkit tk = Toolkit.getDefaultToolkit();
1625
if (tk instanceof SunToolkit) {
1626
((SunToolkit)tk).fireDesktopFontPropertyChanges();
1632
/* "false", "off", ""default" aren't explicitly tested, they
1633
* just fall through to produce a null return which all are equated to
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;
1652
if (aaHint != null) {
1653
RenderingHints map = new RenderingHints(null);
1654
map.put(KEY_TEXT_ANTIALIASING, aaHint);
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.
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) {
1676
(String)AccessController.doPrivileged(
1677
new GetPropertyAction("awt.useSystemAAFontSettings"));
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.
1685
if (!useSystemAAFontSettings) {
1686
desktopFontHints = getDesktopAAHintsByName(systemAAFonts);
1689
/* If its still true, apply the extra condition */
1690
if (useSystemAAFontSettings) {
1691
useSystemAAFontSettings = lastExtraCondition;
1693
checkedSystemAAFontSettings = true;
1695
return useSystemAAFontSettings;
1698
/* A variable defined for the convenience of JDK code */
1699
public static final String DESKTOPFONTHINTS = "awt.font.desktophints";
1701
/* Overridden by subclasses to return platform/desktop specific values */
1702
protected RenderingHints getDesktopAAHints() {
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.
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 */
1721
} else if (desktopFontHints != null) {
1722
/* cloning not necessary as the return value is cloned later, but
1725
return (RenderingHints)(desktopFontHints.clone());
1732
public abstract boolean isDesktopSupported();
1735
* consumeNextKeyTyped() method is not currently used,
1736
* however Swing could use it in the future.
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});
1746
consumeNextKeyTypedMethod.invoke(KeyboardFocusManager.getCurrentKeyboardFocusManager(),
1748
} catch (IllegalAccessException iae) {
1749
iae.printStackTrace();
1750
} catch (InvocationTargetException ite) {
1751
ite.printStackTrace();
1755
protected static void dumpPeers(final PlatformLogger aLog) {
1756
AWTAutoShutdown.getInstance().dumpPeers(aLog);
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
1764
public static Window getContainingWindow(Component comp) {
1765
while (comp != null && !(comp instanceof Window)) {
1766
comp = comp.getParent();
1768
return (Window)comp;
1772
* Returns the value of the system property indicated by the specified key.
1774
public static String getSystemProperty(final String key) {
1775
return (String)AccessController.doPrivileged(new PrivilegedAction() {
1776
public Object run() {
1777
return System.getProperty(key);
1783
* Returns the boolean value of the system property indicated by the specified key.
1785
protected static Boolean getBooleanSystemProperty(String key) {
1786
return Boolean.valueOf(AccessController.
1787
doPrivileged(new GetBooleanAction(key)));
1790
private static Boolean sunAwtDisableMixing = null;
1793
* Returns the value of "sun.awt.disableMixing" property. Default
1794
* value is {@code false}.
1796
public synchronized static boolean getSunAwtDisableMixing() {
1797
if (sunAwtDisableMixing == null) {
1798
sunAwtDisableMixing = getBooleanSystemProperty("sun.awt.disableMixing");
1800
return sunAwtDisableMixing.booleanValue();
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.
1808
public boolean isNativeGTKAvailable() {
1813
public boolean isWindowOpacitySupported() {
1818
public boolean isWindowShapingSupported() {
1823
public boolean isWindowTranslucencySupported() {
1827
public boolean isTranslucencyCapable(GraphicsConfiguration gc) {
1832
* Returns whether or not a containing top level window for the passed
1834
* {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT PERPIXEL_TRANSLUCENT}.
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
1842
public static boolean isContainingTopLevelOpaque(Component c) {
1843
Window w = getContainingWindow(c);
1844
return w != null && w.isOpaque();
1848
* Returns whether or not a containing top level window for the passed
1850
* {@link GraphicsDevice.WindowTranslucency#TRANSLUCENT TRANSLUCENT}.
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
1858
public static boolean isContainingTopLevelTranslucent(Component c) {
1859
Window w = getContainingWindow(c);
1860
return w != null && ((Window)w).getOpacity() < 1.0f;
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
1870
public boolean needUpdateWindow() {
1875
* Descendants of the SunToolkit should override and put their own logic here.
1877
public int getNumberOfButtons(){
1882
* Checks that the given object implements/extends the given
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.
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
1895
public static boolean isInstanceOf(Object obj, String type) {
1896
if (obj == null) return false;
1897
if (type == null) return false;
1899
return isInstanceOf(obj.getClass(), type);
1902
private static boolean isInstanceOf(Class cls, String type) {
1903
if (cls == null) return false;
1905
if (cls.getName().equals(type)) {
1909
for (Class c : cls.getInterfaces()) {
1910
if (c.getName().equals(type)) {
1914
return isInstanceOf(cls.getSuperclass(), type);
1917
///////////////////////////////////////////////////////////////////////////
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
1925
///////////////////////////////////////////////////////////////////////////
1927
public static void setSystemGenerated(AWTEvent e) {
1928
AWTAccessor.getAWTEventAccessor().setSystemGenerated(e);
1931
public static boolean isSystemGenerated(AWTEvent e) {
1932
return AWTAccessor.getAWTEventAccessor().isSystemGenerated(e);
1935
} // class SunToolkit
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().
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.
1947
class PostEventQueue {
1948
private EventQueueItem queueHead = null;
1949
private EventQueueItem queueTail = null;
1950
private final EventQueue eventQueue;
1952
PostEventQueue(EventQueue eq) {
1956
public synchronized boolean noEvents() {
1957
return queueHead == null;
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.
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;
1975
* Enqueue an AWTEvent to be posted to the Java EventQueue.
1977
void postEvent(AWTEvent event) {
1978
EventQueueItem item = new EventQueueItem(event);
1980
synchronized (this) {
1981
if (queueHead == null) {
1982
queueHead = queueTail = item;
1984
queueTail.next = item;
1988
SunToolkit.wakeupEventQueue(eventQueue, event.getSource() == AWTAutoShutdown.getInstance());
1990
} // class PostEventQueue