1 /*
2  * Copyright (c) 2002, 2020, 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.X11;
27 
28 import java.awt.AWTError;
29 import java.awt.AWTException;
30 import java.awt.Button;
31 import java.awt.Canvas;
32 import java.awt.Checkbox;
33 import java.awt.CheckboxMenuItem;
34 import java.awt.Choice;
35 import java.awt.Color;
36 import java.awt.Component;
37 import java.awt.Cursor;
38 import java.awt.Desktop;
39 import java.awt.Dialog;
40 import java.awt.Dimension;
41 import java.awt.EventQueue;
42 import java.awt.FileDialog;
43 import java.awt.Frame;
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.Insets;
50 import java.awt.JobAttributes;
51 import java.awt.Label;
52 import java.awt.Menu;
53 import java.awt.MenuBar;
54 import java.awt.MenuItem;
55 import java.awt.PageAttributes;
56 import java.awt.Panel;
57 import java.awt.Point;
58 import java.awt.PopupMenu;
59 import java.awt.PrintJob;
60 import java.awt.Rectangle;
61 import java.awt.ScrollPane;
62 import java.awt.Scrollbar;
63 import java.awt.SystemColor;
64 import java.awt.SystemTray;
65 import java.awt.Taskbar;
66 import java.awt.TextArea;
67 import java.awt.TextField;
68 import java.awt.Toolkit;
69 import java.awt.TrayIcon;
70 import java.awt.Window;
71 import java.awt.datatransfer.Clipboard;
72 import java.awt.dnd.DragGestureEvent;
73 import java.awt.dnd.DragGestureListener;
74 import java.awt.dnd.DragGestureRecognizer;
75 import java.awt.dnd.DragSource;
76 import java.awt.dnd.InvalidDnDOperationException;
77 import java.awt.dnd.MouseDragGestureRecognizer;
78 import java.awt.dnd.peer.DragSourceContextPeer;
79 import java.awt.event.InputEvent;
80 import java.awt.event.KeyEvent;
81 import java.awt.event.MouseEvent;
82 import java.awt.font.TextAttribute;
83 import java.awt.im.InputMethodHighlight;
84 import java.awt.im.spi.InputMethodDescriptor;
85 import java.awt.peer.ButtonPeer;
86 import java.awt.peer.CanvasPeer;
87 import java.awt.peer.CheckboxMenuItemPeer;
88 import java.awt.peer.CheckboxPeer;
89 import java.awt.peer.ChoicePeer;
90 import java.awt.peer.DesktopPeer;
91 import java.awt.peer.DialogPeer;
92 import java.awt.peer.FileDialogPeer;
93 import java.awt.peer.FontPeer;
94 import java.awt.peer.FramePeer;
95 import java.awt.peer.KeyboardFocusManagerPeer;
96 import java.awt.peer.LabelPeer;
97 import java.awt.peer.ListPeer;
98 import java.awt.peer.MenuBarPeer;
99 import java.awt.peer.MenuItemPeer;
100 import java.awt.peer.MenuPeer;
101 import java.awt.peer.MouseInfoPeer;
102 import java.awt.peer.PanelPeer;
103 import java.awt.peer.PopupMenuPeer;
104 import java.awt.peer.RobotPeer;
105 import java.awt.peer.ScrollPanePeer;
106 import java.awt.peer.ScrollbarPeer;
107 import java.awt.peer.SystemTrayPeer;
108 import java.awt.peer.TaskbarPeer;
109 import java.awt.peer.TextAreaPeer;
110 import java.awt.peer.TextFieldPeer;
111 import java.awt.peer.TrayIconPeer;
112 import java.awt.peer.WindowPeer;
113 import java.beans.PropertyChangeListener;
114 import java.security.AccessController;
115 import java.security.PrivilegedAction;
116 import java.util.ArrayList;
117 import java.util.Collection;
118 import java.util.HashMap;
119 import java.util.Iterator;
120 import java.util.LinkedList;
121 import java.util.Map;
122 import java.util.NoSuchElementException;
123 import java.util.Properties;
124 import java.util.SortedMap;
125 import java.util.TreeMap;
126 import java.util.Vector;
127 
128 import javax.swing.LookAndFeel;
129 import javax.swing.UIDefaults;
130 
131 import sun.awt.AWTAccessor;
132 import sun.awt.AWTPermissions;
133 import sun.awt.AppContext;
134 import sun.awt.DisplayChangedListener;
135 import sun.awt.LightweightFrame;
136 import sun.awt.SunToolkit;
137 import sun.awt.UNIXToolkit;
138 import sun.awt.X11GraphicsConfig;
139 import sun.awt.X11GraphicsDevice;
140 import sun.awt.X11GraphicsEnvironment;
141 import sun.awt.XSettings;
142 import sun.awt.datatransfer.DataTransferer;
143 import sun.awt.util.PerformanceLogger;
144 import sun.awt.util.ThreadGroupUtils;
145 import sun.font.FontConfigManager;
146 import sun.java2d.SunGraphicsEnvironment;
147 import sun.print.PrintJob2D;
148 import sun.security.action.GetBooleanAction;
149 import sun.security.action.GetPropertyAction;
150 import sun.util.logging.PlatformLogger;
151 
152 import static sun.awt.X11.XlibUtil.scaleDown;
153 
154 public final class XToolkit extends UNIXToolkit implements Runnable {
155     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XToolkit");
156     private static final PlatformLogger eventLog = PlatformLogger.getLogger("sun.awt.X11.event.XToolkit");
157     private static final PlatformLogger timeoutTaskLog = PlatformLogger.getLogger("sun.awt.X11.timeoutTask.XToolkit");
158     private static final PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.kye.XToolkit");
159     private static final PlatformLogger backingStoreLog = PlatformLogger.getLogger("sun.awt.X11.backingStore.XToolkit");
160 
161     //There is 400 ms is set by default on Windows and 500 by default on KDE and GNOME.
162     //We use the same hardcoded constant.
163     private static final int AWT_MULTICLICK_DEFAULT_TIME = 500;
164 
165     static final boolean PRIMARY_LOOP = false;
166     static final boolean SECONDARY_LOOP = true;
167 
168     private static String awtAppClassName = null;
169 
170     // the system clipboard - CLIPBOARD selection
171     XClipboard clipboard;
172     // the system selection - PRIMARY selection
173     XClipboard selection;
174 
175     // Dynamic Layout Resize client code setting
176     protected static boolean dynamicLayoutSetting = false;
177 
178     //Is it allowed to generate events assigned to extra mouse buttons.
179     //Set to true by default.
180     private static boolean areExtraMouseButtonsEnabled = true;
181 
182     /**
183      * True when the x settings have been loaded.
184      */
185     private boolean loadedXSettings;
186 
187     /**
188     * XSETTINGS for the default screen.
189      * <p>
190      */
191     private XSettings xs;
192 
193     private FontConfigManager fcManager = new FontConfigManager();
194 
195     static int arrowCursor;
196     static TreeMap<Long, XBaseWindow> winMap = new TreeMap<>();
197     static HashMap<Object, Object> specialPeerMap = new HashMap<>();
198     static HashMap<Long, Collection<XEventDispatcher>> winToDispatcher = new HashMap<>();
199     static UIDefaults uidefaults;
200     static final X11GraphicsEnvironment localEnv;
201     private static final X11GraphicsDevice device;
202     private static final long display;
203     static int awt_multiclick_time;
204     static boolean securityWarningEnabled;
205 
206     /**
207      * Dimensions of default virtual screen in pixels. These values are used to
208      * limit the maximum size of the window.
209      */
210     private static volatile int maxWindowWidthInPixels = -1;
211     private static volatile int maxWindowHeightInPixels = -1;
212 
213     private static XMouseInfoPeer xPeer;
214 
215     static {
initSecurityWarning()216         initSecurityWarning();
217         if (GraphicsEnvironment.isHeadless()) {
218             localEnv = null;
219             device = null;
220             display = 0;
221         } else {
222             localEnv = (X11GraphicsEnvironment) GraphicsEnvironment
223                 .getLocalGraphicsEnvironment();
224             device = (X11GraphicsDevice) localEnv.getDefaultScreenDevice();
225             display = device.getDisplay();
setupModifierMap()226             setupModifierMap();
initIDs()227             initIDs();
setBackingStoreType()228             setBackingStoreType();
229         }
230     }
231 
232     /*
233      * Return (potentially) platform specific display timeout for the
234      * tray icon
235      */
getTrayIconDisplayTimeout()236     static native long getTrayIconDisplayTimeout();
237 
initIDs()238     private static native void initIDs();
waitForEvents(long nextTaskTime)239     static native void waitForEvents(long nextTaskTime);
240     static Thread toolkitThread;
isToolkitThread()241     static boolean isToolkitThread() {
242         return Thread.currentThread() == toolkitThread;
243     }
244 
initSecurityWarning()245     static void initSecurityWarning() {
246         // Enable warning only for internal builds
247         String runtime = AccessController.doPrivileged(
248                              new GetPropertyAction("java.runtime.version"));
249         securityWarningEnabled = (runtime != null && runtime.contains("internal"));
250     }
251 
isSecurityWarningEnabled()252     static boolean isSecurityWarningEnabled() {
253         return securityWarningEnabled;
254     }
255 
awt_output_flush()256     static native void awt_output_flush();
257 
awtFUnlock()258     static void  awtFUnlock() {
259         awtUnlock();
260         awt_output_flush();
261     }
262 
263 
nativeLoadSystemColors(int[] systemColors)264     private native void nativeLoadSystemColors(int[] systemColors);
265 
getUIDefaults()266     static UIDefaults getUIDefaults() {
267         if (uidefaults == null) {
268             initUIDefaults();
269         }
270         return uidefaults;
271     }
272 
273     @Override
loadSystemColors(int[] systemColors)274     public void loadSystemColors(int[] systemColors) {
275         nativeLoadSystemColors(systemColors);
276         MotifColorUtilities.loadSystemColors(systemColors);
277     }
278 
279 
280 
initUIDefaults()281     static void initUIDefaults() {
282         try {
283             // Load Defaults from MotifLookAndFeel
284 
285             // This dummy load is necessary to get SystemColor initialized. !!!!!!
286             Color c = SystemColor.text;
287 
288             LookAndFeel lnf = new XAWTLookAndFeel();
289             uidefaults = lnf.getDefaults();
290         }
291         catch (Exception e)
292         {
293             e.printStackTrace();
294         }
295     }
296 
297     /**
298      * Returns the X11 Display of the default screen device.
299      *
300      * @return X11 Display
301      * @throws AWTError thrown if local GraphicsEnvironment is null, which
302      *         means we are in the headless environment
303      */
getDisplay()304     public static long getDisplay() {
305         if (localEnv == null) {
306             throw new AWTError("Local GraphicsEnvironment must not be null");
307         }
308         return display;
309     }
310 
getDefaultRootWindow()311     public static long getDefaultRootWindow() {
312         awtLock();
313         try {
314             long res = XlibWrapper.RootWindow(XToolkit.getDisplay(),
315                 XlibWrapper.DefaultScreen(XToolkit.getDisplay()));
316 
317             if (res == 0) {
318                throw new IllegalStateException("Root window must not be null");
319             }
320             return res;
321         } finally {
322             awtUnlock();
323         }
324     }
325 
init()326     void init() {
327         awtLock();
328         try {
329             XlibWrapper.XSupportsLocale();
330             if (XlibWrapper.XSetLocaleModifiers("") == null) {
331                 log.finer("X locale modifiers are not supported, using default");
332             }
333             tryXKB();
334 
335             arrowCursor = XlibWrapper.XCreateFontCursor(XToolkit.getDisplay(),
336                 XCursorFontConstants.XC_arrow);
337             final String extraButtons = "sun.awt.enableExtraMouseButtons";
338             AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
339                 areExtraMouseButtonsEnabled =
340                     Boolean.parseBoolean(System.getProperty(extraButtons, "true"));
341                 //set system property if not yet assigned
342                 System.setProperty(extraButtons, ""+areExtraMouseButtonsEnabled);
343                 return null;
344             });
345             // Detect display mode changes
346             XlibWrapper.XSelectInput(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(), XConstants.StructureNotifyMask);
347             XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(), new XEventDispatcher() {
348                 @Override
349                 public void dispatchEvent(XEvent ev) {
350                     if (ev.get_type() == XConstants.ConfigureNotify) {
351                         awtUnlock();
352                         try {
353                             ((X11GraphicsEnvironment)GraphicsEnvironment.
354                              getLocalGraphicsEnvironment()).
355                                 displayChanged();
356                         } finally {
357                             awtLock();
358                         }
359                     }
360                 }
361             });
362         } finally {
363             awtUnlock();
364         }
365         PrivilegedAction<Void> a = () -> {
366             Runnable r = () -> {
367                 XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance();
368                 if (peer != null) {
369                     peer.dispose();
370                 }
371                 if (xs != null) {
372                     ((XAWTXSettings)xs).dispose();
373                 }
374                 freeXKB();
375                 if (log.isLoggable(PlatformLogger.Level.FINE)) {
376                     dumpPeers();
377                 }
378             };
379             String name = "XToolkt-Shutdown-Thread";
380             Thread shutdownThread = new Thread(
381                     ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false);
382             shutdownThread.setContextClassLoader(null);
383             Runtime.getRuntime().addShutdownHook(shutdownThread);
384             return null;
385         };
386         AccessController.doPrivileged(a);
387     }
388 
getCorrectXIDString(String val)389     static String getCorrectXIDString(String val) {
390         if (val != null) {
391             return val.replace('.', '-');
392         } else {
393             return val;
394         }
395     }
396 
getEnv(String key)397     static native String getEnv(String key);
398 
399 
getAWTAppClassName()400     static String getAWTAppClassName() {
401         return awtAppClassName;
402     }
403 
XToolkit()404     public XToolkit() {
405         super();
406         if (PerformanceLogger.loggingEnabled()) {
407             PerformanceLogger.setTime("XToolkit construction");
408         }
409 
410         if (!GraphicsEnvironment.isHeadless()) {
411             String mainClassName = null;
412 
413             StackTraceElement[] trace = (new Throwable()).getStackTrace();
414             int bottom = trace.length - 1;
415             if (bottom >= 0) {
416                 mainClassName = trace[bottom].getClassName();
417             }
418             if (mainClassName == null || mainClassName.isEmpty()) {
419                 mainClassName = "AWT";
420             }
421             awtAppClassName = getCorrectXIDString(mainClassName);
422 
423             init();
424             XWM.init();
425 
426             toolkitThread = AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
427                 String name = "AWT-XAWT";
428                 Thread thread = new Thread(
429                         ThreadGroupUtils.getRootThreadGroup(), this, name,
430                         0, false);
431                 thread.setContextClassLoader(null);
432                 thread.setPriority(Thread.NORM_PRIORITY + 1);
433                 thread.setDaemon(true);
434                 return thread;
435             });
436             toolkitThread.start();
437         }
438     }
439 
440     @Override
createButton(Button target)441     public ButtonPeer createButton(Button target) {
442         ButtonPeer peer = new XButtonPeer(target);
443         targetCreatedPeer(target, peer);
444         return peer;
445     }
446 
447     @Override
createLightweightFrame(LightweightFrame target)448     public FramePeer createLightweightFrame(LightweightFrame target) {
449         FramePeer peer = new XLightweightFramePeer(target);
450         targetCreatedPeer(target, peer);
451         return peer;
452     }
453 
454     @Override
createFrame(Frame target)455     public FramePeer createFrame(Frame target) {
456         FramePeer peer = new XFramePeer(target);
457         targetCreatedPeer(target, peer);
458         return peer;
459     }
460 
addToWinMap(long window, XBaseWindow xwin)461     static void addToWinMap(long window, XBaseWindow xwin)
462     {
463         synchronized(winMap) {
464             winMap.put(Long.valueOf(window),xwin);
465         }
466     }
467 
removeFromWinMap(long window, XBaseWindow xwin)468     static void removeFromWinMap(long window, XBaseWindow xwin) {
469         synchronized(winMap) {
470             winMap.remove(Long.valueOf(window));
471         }
472     }
windowToXWindow(long window)473     static XBaseWindow windowToXWindow(long window) {
474         synchronized(winMap) {
475             return winMap.get(Long.valueOf(window));
476         }
477     }
478 
addEventDispatcher(long window, XEventDispatcher dispatcher)479     static void addEventDispatcher(long window, XEventDispatcher dispatcher) {
480         synchronized(winToDispatcher) {
481             Long key = Long.valueOf(window);
482             Collection<XEventDispatcher> dispatchers = winToDispatcher.get(key);
483             if (dispatchers == null) {
484                 dispatchers = new Vector<>();
485                 winToDispatcher.put(key, dispatchers);
486             }
487             dispatchers.add(dispatcher);
488         }
489     }
removeEventDispatcher(long window, XEventDispatcher dispatcher)490     static void removeEventDispatcher(long window, XEventDispatcher dispatcher) {
491         synchronized(winToDispatcher) {
492             Long key = Long.valueOf(window);
493             Collection<XEventDispatcher> dispatchers = winToDispatcher.get(key);
494             if (dispatchers != null) {
495                 dispatchers.remove(dispatcher);
496             }
497         }
498     }
499 
500     private Point lastCursorPos;
501 
502     /**
503      * Returns whether there is last remembered cursor position.  The
504      * position is remembered from X mouse events on our peers.  The
505      * position is stored in {@code p}.
506      * @return true, if there is remembered last cursor position,
507      * false otherwise
508      */
getLastCursorPos(Point p)509     boolean getLastCursorPos(Point p) {
510         awtLock();
511         try {
512             if (lastCursorPos == null) {
513                 return false;
514             }
515             p.setLocation(lastCursorPos);
516             return true;
517         } finally {
518             awtUnlock();
519         }
520     }
521 
processGlobalMotionEvent(XEvent e, XBaseWindow win)522     private void processGlobalMotionEvent(XEvent e, XBaseWindow win) {
523         // Only our windows guaranteely generate MotionNotify, so we
524         // should track enter/leave, to catch the moment when to
525         // switch to XQueryPointer
526         if (e.get_type() == XConstants.MotionNotify) {
527             XMotionEvent ev = e.get_xmotion();
528             awtLock();
529             try {
530                 if (lastCursorPos == null) {
531                     lastCursorPos = new Point(win.scaleDown(ev.get_x_root()),
532                                               win.scaleDown(ev.get_y_root()));
533                 } else {
534                     lastCursorPos.setLocation(win.scaleDown(ev.get_x_root()),
535                                               win.scaleDown(ev.get_y_root()));
536                 }
537             } finally {
538                 awtUnlock();
539             }
540         } else if (e.get_type() == XConstants.LeaveNotify) {
541             // Leave from our window
542             awtLock();
543             try {
544                 lastCursorPos = null;
545             } finally {
546                 awtUnlock();
547             }
548         } else if (e.get_type() == XConstants.EnterNotify) {
549             // Entrance into our window
550             XCrossingEvent ev = e.get_xcrossing();
551             awtLock();
552             try {
553                 if (lastCursorPos == null) {
554                     lastCursorPos = new Point(win.scaleDown(ev.get_x_root()),
555                                               win.scaleDown(ev.get_y_root()));
556                 } else {
557                     lastCursorPos.setLocation(win.scaleDown(ev.get_x_root()),
558                                               win.scaleDown(ev.get_y_root()));
559                 }
560             } finally {
561                 awtUnlock();
562             }
563         }
564     }
565 
566     public interface XEventListener {
eventProcessed(XEvent e)567         public void eventProcessed(XEvent e);
568     }
569 
570     private Collection<XEventListener> listeners = new LinkedList<XEventListener>();
571 
addXEventListener(XEventListener listener)572     public void addXEventListener(XEventListener listener) {
573         synchronized (listeners) {
574             listeners.add(listener);
575         }
576     }
577 
notifyListeners(XEvent xev)578     private void notifyListeners(XEvent xev) {
579         synchronized (listeners) {
580             if (listeners.size() == 0) return;
581 
582             XEvent copy = xev.clone();
583             try {
584                 for (XEventListener listener : listeners) {
585                     listener.eventProcessed(copy);
586                 }
587             } finally {
588                 copy.dispose();
589             }
590         }
591     }
592 
dispatchEvent(XEvent ev)593     private void dispatchEvent(XEvent ev) {
594         final XAnyEvent xany = ev.get_xany();
595 
596         XBaseWindow baseWindow = windowToXWindow(xany.get_window());
597         if (baseWindow != null && (ev.get_type() == XConstants.MotionNotify
598                 || ev.get_type() == XConstants.EnterNotify
599                 || ev.get_type() == XConstants.LeaveNotify)) {
600             processGlobalMotionEvent(ev, baseWindow);
601         }
602 
603         if( ev.get_type() == XConstants.MappingNotify ) {
604             // The 'window' field in this event is unused.
605             // This application itself does nothing to initiate such an event
606             // (no calls of XChangeKeyboardMapping etc.).
607             // SunRay server sends this event to the application once on every
608             // keyboard (not just layout) change which means, quite seldom.
609             XlibWrapper.XRefreshKeyboardMapping(ev.pData);
610             resetKeyboardSniffer();
611             setupModifierMap();
612         }
613         XBaseWindow.dispatchToWindow(ev);
614 
615         Collection<XEventDispatcher> dispatchers = null;
616         synchronized(winToDispatcher) {
617             Long key = Long.valueOf(xany.get_window());
618             dispatchers = winToDispatcher.get(key);
619             if (dispatchers != null) { // Clone it to avoid synchronization during dispatching
620                 dispatchers = new Vector<>(dispatchers);
621             }
622         }
623         if (dispatchers != null) {
624             Iterator<XEventDispatcher> iter = dispatchers.iterator();
625             while (iter.hasNext()) {
626                 XEventDispatcher disp = iter.next();
627                 disp.dispatchEvent(ev);
628             }
629         }
630         notifyListeners(ev);
631     }
632 
processException(Throwable thr)633     static void processException(Throwable thr) {
634         if (log.isLoggable(PlatformLogger.Level.WARNING)) {
635             log.warning("Exception on Toolkit thread", thr);
636         }
637     }
638 
awt_toolkit_init()639     static native void awt_toolkit_init();
640 
641     @Override
run()642     public void run() {
643         awt_toolkit_init();
644         run(PRIMARY_LOOP);
645     }
646 
run(boolean loop)647     public void run(boolean loop)
648     {
649         XEvent ev = new XEvent();
650         while(true) {
651             // Fix for 6829923: we should gracefully handle toolkit thread interruption
652             if (Thread.currentThread().isInterrupted()) {
653                 // We expect interruption from the AppContext.dispose() method only.
654                 // If the thread is interrupted from another place, let's skip it
655                 // for compatibility reasons. Probably some time later we'll remove
656                 // the check for AppContext.isDisposed() and will unconditionally
657                 // break the loop here.
658                 if (AppContext.getAppContext().isDisposed()) {
659                     break;
660                 }
661             }
662             awtLock();
663             try {
664                 if (loop == SECONDARY_LOOP) {
665                     // In the secondary loop we may have already acquired awt_lock
666                     // several times, so waitForEvents() might be unable to release
667                     // the awt_lock and this causes lock up.
668                     // For now, we just avoid waitForEvents in the secondary loop.
669                     if (!XlibWrapper.XNextSecondaryLoopEvent(getDisplay(),ev.pData)) {
670                         break;
671                     }
672                 } else {
673                     callTimeoutTasks();
674                     // If no events are queued, waitForEvents() causes calls to
675                     // awtUnlock(), awtJNI_ThreadYield, poll, awtLock(),
676                     // so it spends most of its time in poll, without holding the lock.
677                     while ((XlibWrapper.XEventsQueued(getDisplay(), XConstants.QueuedAfterReading) == 0) &&
678                            (XlibWrapper.XEventsQueued(getDisplay(), XConstants.QueuedAfterFlush) == 0)) {
679                         callTimeoutTasks();
680                         waitForEvents(getNextTaskTime());
681                     }
682                     XlibWrapper.XNextEvent(getDisplay(),ev.pData);
683                 }
684 
685                 if (ev.get_type() != XConstants.NoExpose) {
686                     eventNumber++;
687                 }
688                 if (awt_UseXKB_Calls && ev.get_type() ==  awt_XKBBaseEventCode) {
689                     processXkbChanges(ev);
690                 }
691 
692                 if (XDropTargetEventProcessor.processEvent(ev) ||
693                     XDragSourceContextPeer.processEvent(ev)) {
694                     continue;
695                 }
696 
697                 if (eventLog.isLoggable(PlatformLogger.Level.FINER)) {
698                     eventLog.finer("{0}", ev);
699                 }
700 
701                 // Check if input method consumes the event
702                 long w = 0;
703                 if (windowToXWindow(ev.get_xany().get_window()) != null) {
704                     Component owner =
705                         XKeyboardFocusManagerPeer.getInstance().getCurrentFocusOwner();
706                     if (owner != null) {
707                         XWindow ownerWindow = AWTAccessor.getComponentAccessor().getPeer(owner);
708                         if (ownerWindow != null) {
709                             w = ownerWindow.getContentWindow();
710                         }
711                     }
712                 }
713                 if (keyEventLog.isLoggable(PlatformLogger.Level.FINE) && (
714                         ev.get_type() == XConstants.KeyPress
715                                 || ev.get_type() == XConstants.KeyRelease)) {
716                     keyEventLog.fine("before XFilterEvent:" + ev);
717                 }
718                 if (XlibWrapper.XFilterEvent(ev.getPData(), w)) {
719                     continue;
720                 }
721                 if (keyEventLog.isLoggable(PlatformLogger.Level.FINE) && (
722                         ev.get_type() == XConstants.KeyPress
723                                 || ev.get_type() == XConstants.KeyRelease)) {
724                     keyEventLog.fine(
725                             "after XFilterEvent:" + ev); // IS THIS CORRECT?
726                 }
727 
728                 dispatchEvent(ev);
729             } catch (ThreadDeath td) {
730                 XBaseWindow.ungrabInput();
731                 return;
732             } catch (Throwable thr) {
733                 XBaseWindow.ungrabInput();
734                 processException(thr);
735             } finally {
736                 awtUnlock();
737             }
738         }
739     }
740 
741     /**
742      * Listener installed to detect display changes.
743      */
744     private static final DisplayChangedListener displayChangedHandler =
745             new DisplayChangedListener() {
746                 @Override
747                 public void displayChanged() {
748                     // 7045370: Reset the cached values
749                     XToolkit.maxWindowWidthInPixels = -1;
750                     XToolkit.maxWindowHeightInPixels = -1;
751                 }
752 
753                 @Override
754                 public void paletteChanged() {
755                 }
756             };
757 
758     static {
759         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
760         if (ge instanceof SunGraphicsEnvironment) {
addDisplayChangedListener( displayChangedHandler)761             ((SunGraphicsEnvironment) ge).addDisplayChangedListener(
762                     displayChangedHandler);
763         }
764     }
765 
initScreenSize()766     private static void initScreenSize() {
767         if (maxWindowWidthInPixels == -1 || maxWindowHeightInPixels == -1) {
768             awtLock();
769             try {
770                 XWindowAttributes pattr = new XWindowAttributes();
771                 try {
772                     XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
773                                                      XToolkit.getDefaultRootWindow(),
774                                                      pattr.pData);
775                     maxWindowWidthInPixels = pattr.get_width();
776                     maxWindowHeightInPixels = pattr.get_height();
777                 } finally {
778                     pattr.dispose();
779                 }
780             } finally {
781                 awtUnlock();
782             }
783         }
784     }
785 
getMaxWindowWidthInPixels()786     static int getMaxWindowWidthInPixels() {
787         initScreenSize();
788         return maxWindowWidthInPixels;
789     }
790 
getMaxWindowHeightInPixels()791     static int getMaxWindowHeightInPixels() {
792         initScreenSize();
793         return maxWindowHeightInPixels;
794     }
795 
getWorkArea(long root, int scale)796     private static Rectangle getWorkArea(long root, int scale)
797     {
798         XAtom XA_NET_WORKAREA = XAtom.get("_NET_WORKAREA");
799 
800         long native_ptr = Native.allocateLongArray(4);
801         try
802         {
803             boolean workareaPresent = XA_NET_WORKAREA.getAtomData(root,
804                 XAtom.XA_CARDINAL, native_ptr, 4);
805             if (workareaPresent)
806             {
807                 int rootX = (int)Native.getLong(native_ptr, 0);
808                 int rootY = (int)Native.getLong(native_ptr, 1);
809                 int rootWidth = (int)Native.getLong(native_ptr, 2);
810                 int rootHeight = (int)Native.getLong(native_ptr, 3);
811 
812                 return new Rectangle(scaleDown(rootX, scale),
813                                      scaleDown(rootY, scale),
814                                      scaleDown(rootWidth, scale),
815                                      scaleDown(rootHeight, scale));
816             }
817         }
818         finally
819         {
820             XlibWrapper.unsafe.freeMemory(native_ptr);
821         }
822 
823         return null;
824     }
825 
826     /*
827      * If the current window manager supports _NET protocol then the screen
828      * insets are calculated using _NET_WORKAREA property of the root window.
829      * <p>
830      * Note that _NET_WORKAREA is a rectangular area and it does not work
831      * well in the Xinerama mode.
832      * <p>
833      * We will trust the part of this rectangular area only if it starts at the
834      * requested graphics configuration. Below is an example when the
835      * _NET_WORKAREA intersects with the requested graphics configuration but
836      * produces wrong result.
837      *
838      *         //<-x1,y1///////
839      *         //            // ////////////////
840      *         //  SCREEN1   // // SCREEN2    //
841      *         // ********** // //     x2,y2->//
842      *         //////////////// //            //
843      *                          ////////////////
844      *
845      * When two screens overlap and the first contains a dock(*****), then
846      * _NET_WORKAREA may start at point x1,y1 and end at point x2,y2.
847      */
848     @Override
getScreenInsets(final GraphicsConfiguration gc)849     public Insets getScreenInsets(final GraphicsConfiguration gc) {
850         GraphicsDevice gd = gc.getDevice();
851         XNETProtocol np = XWM.getWM().getNETProtocol();
852         if (np == null || !(gd instanceof X11GraphicsDevice) || !np.active()) {
853             return super.getScreenInsets(gc);
854         }
855 
856         XToolkit.awtLock();
857         try {
858             X11GraphicsDevice x11gd = (X11GraphicsDevice) gd;
859             long root = XlibUtil.getRootWindow(x11gd.getScreen());
860             Rectangle workArea = getWorkArea(root, x11gd.getScaleFactor());
861             Rectangle screen = gc.getBounds();
862             if (workArea != null && screen.contains(workArea.getLocation())) {
863                 workArea = workArea.intersection(screen);
864                 int top = workArea.y - screen.y;
865                 int left = workArea.x - screen.x;
866                 int bottom = screen.height - workArea.height - top;
867                 int right = screen.width - workArea.width - left;
868                 return new Insets(top, left, bottom, right);
869             }
870             // Note that it is better to return zeros than inadequate values
871             return new Insets(0, 0, 0, 0);
872         } finally {
873             XToolkit.awtUnlock();
874         }
875     }
876 
877     /*
878      * The current implementation of disabling background erasing for
879      * canvases is that we don't set any native background color
880      * (with XSetWindowBackground) for the canvas window. However,
881      * this color is set in the peer constructor - see
882      * XWindow.postInit() for details. That's why this method from
883      * SunToolkit is not overridden in XToolkit: it's too late to
884      * disable background erasing :(
885      */
886     /*
887     @Override
888     public void disableBackgroundErase(Canvas canvas) {
889         XCanvasPeer peer = (XCanvasPeer)canvas.getPeer();
890         if (peer == null) {
891             throw new IllegalStateException("Canvas must have a valid peer");
892         }
893         peer.disableBackgroundErase();
894     }
895     */
896 
897     // Need this for XMenuItemPeer.
targetToPeer(Object target)898     protected static Object targetToPeer(Object target) {
899         Object p=null;
900         if (target != null && !GraphicsEnvironment.isHeadless()) {
901             p = specialPeerMap.get(target);
902         }
903         if (p != null) return p;
904         else
905             return SunToolkit.targetToPeer(target);
906     }
907 
908     // Need this for XMenuItemPeer.
targetDisposedPeer(Object target, Object peer)909     protected static void targetDisposedPeer(Object target, Object peer) {
910         SunToolkit.targetDisposedPeer(target, peer);
911     }
912 
913     @Override
createRobot(GraphicsDevice screen)914     public RobotPeer createRobot(GraphicsDevice screen) throws AWTException {
915         if (screen instanceof X11GraphicsDevice) {
916             return new XRobotPeer((X11GraphicsDevice) screen);
917         }
918         return super.createRobot(screen);
919     }
920 
921   /*
922      * On X, support for dynamic layout on resizing is governed by the
923      * window manager.  If the window manager supports it, it happens
924      * automatically.  The setter method for this property is
925      * irrelevant on X.
926      */
927     @Override
setDynamicLayout(boolean b)928     public void setDynamicLayout(boolean b) {
929         dynamicLayoutSetting = b;
930     }
931 
932     @Override
isDynamicLayoutSet()933     protected boolean isDynamicLayoutSet() {
934         return dynamicLayoutSetting;
935     }
936 
937     /* Called from isDynamicLayoutActive() and from
938      * lazilyLoadDynamicLayoutSupportedProperty()
939      */
isDynamicLayoutSupported()940     protected boolean isDynamicLayoutSupported() {
941         return XWM.getWM().supportsDynamicLayout();
942     }
943 
944     @Override
isDynamicLayoutActive()945     public boolean isDynamicLayoutActive() {
946         return isDynamicLayoutSupported();
947     }
948 
949     @Override
getFontPeer(String name, int style)950     public FontPeer getFontPeer(String name, int style){
951         return new XFontPeer(name, style);
952     }
953 
954     @Override
createDragSourceContextPeer(DragGestureEvent dge)955     public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {
956         final LightweightFrame f = SunToolkit.getLightweightFrame(dge.getComponent());
957         if (f != null) {
958             return f.createDragSourceContextPeer(dge);
959         }
960 
961         return XDragSourceContextPeer.createDragSourceContextPeer(dge);
962     }
963 
964     @Override
965     @SuppressWarnings("unchecked")
966     public <T extends DragGestureRecognizer> T
createDragGestureRecognizer(Class<T> recognizerClass, DragSource ds, Component c, int srcActions, DragGestureListener dgl)967     createDragGestureRecognizer(Class<T> recognizerClass,
968                     DragSource ds,
969                     Component c,
970                     int srcActions,
971                     DragGestureListener dgl)
972     {
973         final LightweightFrame f = SunToolkit.getLightweightFrame(c);
974         if (f != null) {
975             return f.createDragGestureRecognizer(recognizerClass, ds, c, srcActions, dgl);
976         }
977 
978         if (MouseDragGestureRecognizer.class.equals(recognizerClass))
979             return (T)new XMouseDragGestureRecognizer(ds, c, srcActions, dgl);
980         else
981             return null;
982     }
983 
984     @Override
createCheckboxMenuItem(CheckboxMenuItem target)985     public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) {
986         XCheckboxMenuItemPeer peer = new XCheckboxMenuItemPeer(target);
987         //vb157120: looks like we don't need to map menu items
988         //in new menus implementation
989         //targetCreatedPeer(target, peer);
990         return peer;
991     }
992 
993     @Override
createMenuItem(MenuItem target)994     public MenuItemPeer createMenuItem(MenuItem target) {
995         XMenuItemPeer peer = new XMenuItemPeer(target);
996         //vb157120: looks like we don't need to map menu items
997         //in new menus implementation
998         //targetCreatedPeer(target, peer);
999         return peer;
1000     }
1001 
1002     @Override
createTextField(TextField target)1003     public TextFieldPeer createTextField(TextField target) {
1004         TextFieldPeer  peer = new XTextFieldPeer(target);
1005         targetCreatedPeer(target, peer);
1006         return peer;
1007     }
1008 
1009     @Override
createLabel(Label target)1010     public LabelPeer createLabel(Label target) {
1011         LabelPeer  peer = new XLabelPeer(target);
1012         targetCreatedPeer(target, peer);
1013         return peer;
1014     }
1015 
1016     @Override
createList(java.awt.List target)1017     public ListPeer createList(java.awt.List target) {
1018         ListPeer peer = new XListPeer(target);
1019         targetCreatedPeer(target, peer);
1020         return peer;
1021     }
1022 
1023     @Override
createCheckbox(Checkbox target)1024     public CheckboxPeer createCheckbox(Checkbox target) {
1025         CheckboxPeer peer = new XCheckboxPeer(target);
1026         targetCreatedPeer(target, peer);
1027         return peer;
1028     }
1029 
1030     @Override
createScrollbar(Scrollbar target)1031     public ScrollbarPeer createScrollbar(Scrollbar target) {
1032         XScrollbarPeer peer = new XScrollbarPeer(target);
1033         targetCreatedPeer(target, peer);
1034         return peer;
1035     }
1036 
1037     @Override
createScrollPane(ScrollPane target)1038     public ScrollPanePeer createScrollPane(ScrollPane target) {
1039         XScrollPanePeer peer = new XScrollPanePeer(target);
1040         targetCreatedPeer(target, peer);
1041         return peer;
1042     }
1043 
1044     @Override
createTextArea(TextArea target)1045     public TextAreaPeer createTextArea(TextArea target) {
1046         TextAreaPeer peer = new XTextAreaPeer(target);
1047         targetCreatedPeer(target, peer);
1048         return peer;
1049     }
1050 
1051     @Override
createChoice(Choice target)1052     public ChoicePeer createChoice(Choice target) {
1053         XChoicePeer peer = new XChoicePeer(target);
1054         targetCreatedPeer(target, peer);
1055         return peer;
1056     }
1057 
1058     @Override
createCanvas(Canvas target)1059     public CanvasPeer createCanvas(Canvas target) {
1060         XCanvasPeer peer = (isXEmbedServerRequested() ? new XEmbedCanvasPeer(target) : new XCanvasPeer(target));
1061         targetCreatedPeer(target, peer);
1062         return peer;
1063     }
1064 
1065     @Override
createPanel(Panel target)1066     public PanelPeer createPanel(Panel target) {
1067         PanelPeer peer = new XPanelPeer(target);
1068         targetCreatedPeer(target, peer);
1069         return peer;
1070     }
1071 
1072     @Override
createWindow(Window target)1073     public WindowPeer createWindow(Window target) {
1074         WindowPeer peer = new XWindowPeer(target);
1075         targetCreatedPeer(target, peer);
1076         return peer;
1077     }
1078 
1079     @Override
createDialog(Dialog target)1080     public DialogPeer createDialog(Dialog target) {
1081         DialogPeer peer = new XDialogPeer(target);
1082         targetCreatedPeer(target, peer);
1083         return peer;
1084     }
1085 
1086     private static Boolean sunAwtDisableGtkFileDialogs = null;
1087 
1088     /**
1089      * Returns the value of "sun.awt.disableGtkFileDialogs" property. Default
1090      * value is {@code false}.
1091      */
getSunAwtDisableGtkFileDialogs()1092     public static synchronized boolean getSunAwtDisableGtkFileDialogs() {
1093         if (sunAwtDisableGtkFileDialogs == null) {
1094             sunAwtDisableGtkFileDialogs = AccessController.doPrivileged(
1095                                               new GetBooleanAction("sun.awt.disableGtkFileDialogs"));
1096         }
1097         return sunAwtDisableGtkFileDialogs.booleanValue();
1098     }
1099 
1100     @Override
createFileDialog(FileDialog target)1101     public FileDialogPeer createFileDialog(FileDialog target) {
1102         FileDialogPeer peer = null;
1103         // The current GtkFileChooser is available from GTK+ 2.4
1104         if (!getSunAwtDisableGtkFileDialogs() &&
1105                       (checkGtkVersion(2, 4, 0) || checkGtkVersion(3, 0, 0))) {
1106             peer = new GtkFileDialogPeer(target);
1107         } else {
1108             peer = new XFileDialogPeer(target);
1109         }
1110         targetCreatedPeer(target, peer);
1111         return peer;
1112     }
1113 
1114     @Override
createMenuBar(MenuBar target)1115     public MenuBarPeer createMenuBar(MenuBar target) {
1116         XMenuBarPeer peer = new XMenuBarPeer(target);
1117         targetCreatedPeer(target, peer);
1118         return peer;
1119     }
1120 
1121     @Override
createMenu(Menu target)1122     public MenuPeer createMenu(Menu target) {
1123         XMenuPeer peer = new XMenuPeer(target);
1124         //vb157120: looks like we don't need to map menu items
1125         //in new menus implementation
1126         //targetCreatedPeer(target, peer);
1127         return peer;
1128     }
1129 
1130     @Override
createPopupMenu(PopupMenu target)1131     public PopupMenuPeer createPopupMenu(PopupMenu target) {
1132         XPopupMenuPeer peer = new XPopupMenuPeer(target);
1133         targetCreatedPeer(target, peer);
1134         return peer;
1135     }
1136 
1137     @Override
getMouseInfoPeer()1138     public synchronized MouseInfoPeer getMouseInfoPeer() {
1139         if (xPeer == null) {
1140             xPeer = new XMouseInfoPeer();
1141         }
1142         return xPeer;
1143     }
1144 
createEmbeddedFrame(XEmbeddedFrame target)1145     public XEmbeddedFramePeer createEmbeddedFrame(XEmbeddedFrame target)
1146     {
1147         XEmbeddedFramePeer peer = new XEmbeddedFramePeer(target);
1148         targetCreatedPeer(target, peer);
1149         return peer;
1150     }
1151 
createEmbedProxy(XEmbedChildProxy target)1152     XEmbedChildProxyPeer createEmbedProxy(XEmbedChildProxy target) {
1153         XEmbedChildProxyPeer peer = new XEmbedChildProxyPeer(target);
1154         targetCreatedPeer(target, peer);
1155         return peer;
1156     }
1157 
1158     @Override
getKeyboardFocusManagerPeer()1159     public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() throws HeadlessException {
1160         return XKeyboardFocusManagerPeer.getInstance();
1161     }
1162 
1163     /**
1164      * Returns a new custom cursor.
1165      */
1166     @Override
createCustomCursor(Image cursor, Point hotSpot, String name)1167     public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
1168       throws IndexOutOfBoundsException {
1169         return new XCustomCursor(cursor, hotSpot, name);
1170     }
1171 
1172     @Override
createTrayIcon(TrayIcon target)1173     public TrayIconPeer createTrayIcon(TrayIcon target)
1174       throws HeadlessException, AWTException
1175     {
1176         TrayIconPeer peer = new XTrayIconPeer(target);
1177         targetCreatedPeer(target, peer);
1178         return peer;
1179     }
1180 
1181     @Override
createSystemTray(SystemTray target)1182     public SystemTrayPeer createSystemTray(SystemTray target) throws HeadlessException {
1183         SystemTrayPeer peer = new XSystemTrayPeer(target);
1184         return peer;
1185     }
1186 
1187     @Override
isTraySupported()1188     public boolean isTraySupported() {
1189         XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance();
1190         if (peer != null) {
1191             return peer.isAvailable();
1192         }
1193         return false;
1194     }
1195 
1196     @Override
getDataTransferer()1197     public DataTransferer getDataTransferer() {
1198         return XDataTransferer.getInstanceImpl();
1199     }
1200 
1201     /**
1202      * Returns the supported cursor size
1203      */
1204     @Override
getBestCursorSize(int preferredWidth, int preferredHeight)1205     public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) {
1206         return XCustomCursor.getBestCursorSize(
1207                                                java.lang.Math.max(1,preferredWidth), java.lang.Math.max(1,preferredHeight));
1208     }
1209 
1210 
1211     @Override
getMaximumCursorColors()1212     public int getMaximumCursorColors() {
1213         return 2;  // Black and white.
1214     }
1215 
1216     @Override
mapInputMethodHighlight( InputMethodHighlight highlight)1217     public Map<TextAttribute, ?> mapInputMethodHighlight( InputMethodHighlight highlight) {
1218         return XInputMethod.mapInputMethodHighlight(highlight);
1219     }
1220     @Override
getLockingKeyState(int key)1221     public boolean getLockingKeyState(int key) {
1222         if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK ||
1223                key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) {
1224             throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState");
1225         }
1226         awtLock();
1227         try {
1228             return getModifierState( key );
1229         } finally {
1230             awtUnlock();
1231         }
1232     }
1233 
1234     @Override
getSystemClipboard()1235     public  Clipboard getSystemClipboard() {
1236         SecurityManager security = System.getSecurityManager();
1237         if (security != null) {
1238             security.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION);
1239         }
1240         synchronized (this) {
1241             if (clipboard == null) {
1242                 clipboard = new XClipboard("System", "CLIPBOARD");
1243             }
1244         }
1245         return clipboard;
1246     }
1247 
1248     @Override
getSystemSelection()1249     public Clipboard getSystemSelection() {
1250         SecurityManager security = System.getSecurityManager();
1251         if (security != null) {
1252             security.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION);
1253         }
1254         synchronized (this) {
1255             if (selection == null) {
1256                 selection = new XClipboard("Selection", "PRIMARY");
1257             }
1258         }
1259         return selection;
1260     }
1261 
1262     @Override
beep()1263     public void beep() {
1264         awtLock();
1265         try {
1266             XlibWrapper.XBell(getDisplay(), 0);
1267             XlibWrapper.XFlush(getDisplay());
1268         } finally {
1269             awtUnlock();
1270         }
1271     }
1272 
1273     @Override
getPrintJob(final Frame frame, final String doctitle, final Properties props)1274     public PrintJob getPrintJob(final Frame frame, final String doctitle,
1275                                 final Properties props) {
1276 
1277         if (frame == null) {
1278             throw new NullPointerException("frame must not be null");
1279         }
1280 
1281         PrintJob2D printJob = new PrintJob2D(frame, doctitle, props);
1282 
1283         if (printJob.printDialog() == false) {
1284             printJob = null;
1285         }
1286         return printJob;
1287     }
1288 
1289     @Override
getPrintJob(final Frame frame, final String doctitle, final JobAttributes jobAttributes, final PageAttributes pageAttributes)1290     public PrintJob getPrintJob(final Frame frame, final String doctitle,
1291                 final JobAttributes jobAttributes,
1292                 final PageAttributes pageAttributes)
1293     {
1294         if (frame == null) {
1295             throw new NullPointerException("frame must not be null");
1296         }
1297 
1298         PrintJob2D printJob = new PrintJob2D(frame, doctitle,
1299                                              jobAttributes, pageAttributes);
1300 
1301         if (printJob.printDialog() == false) {
1302             printJob = null;
1303         }
1304 
1305         return printJob;
1306     }
1307 
XSync()1308     static void XSync() {
1309         awtLock();
1310         try {
1311             XlibWrapper.XSync(getDisplay(),0);
1312         } finally {
1313             awtUnlock();
1314         }
1315     }
1316 
1317     @Override
getScreenResolution()1318     public int getScreenResolution() {
1319         long display = getDisplay();
1320         awtLock();
1321         try {
1322             return (int) ((XlibWrapper.DisplayWidth(display,
1323                 XlibWrapper.DefaultScreen(display)) * 25.4) /
1324                     XlibWrapper.DisplayWidthMM(display,
1325                 XlibWrapper.DefaultScreen(display)));
1326         } finally {
1327             awtUnlock();
1328         }
1329     }
1330 
getDefaultXColormap()1331     static native long getDefaultXColormap();
1332 
1333     /**
1334      * Returns a new input method adapter descriptor for native input methods.
1335      */
1336     @Override
getInputMethodAdapterDescriptor()1337     public InputMethodDescriptor getInputMethodAdapterDescriptor() throws AWTException {
1338         return new XInputMethodDescriptor();
1339     }
1340 
1341     /**
1342      * Returns whether enableInputMethods should be set to true for peered
1343      * TextComponent instances on this platform. True by default.
1344      */
1345     @Override
enableInputMethodsForTextComponent()1346     public boolean enableInputMethodsForTextComponent() {
1347         return true;
1348     }
1349 
getMultiClickTime()1350     static int getMultiClickTime() {
1351         if (awt_multiclick_time == 0) {
1352             initializeMultiClickTime();
1353         }
1354         return awt_multiclick_time;
1355     }
initializeMultiClickTime()1356     static void initializeMultiClickTime() {
1357         awtLock();
1358         try {
1359             try {
1360                 String multiclick_time_query = XlibWrapper.XGetDefault(XToolkit.getDisplay(), "*", "multiClickTime");
1361                 if (multiclick_time_query != null) {
1362                     awt_multiclick_time = (int)Long.parseLong(multiclick_time_query);
1363                 } else {
1364                     multiclick_time_query = XlibWrapper.XGetDefault(XToolkit.getDisplay(),
1365                                                                     "OpenWindows", "MultiClickTimeout");
1366                     if (multiclick_time_query != null) {
1367                         /* Note: OpenWindows.MultiClickTimeout is in tenths of
1368                            a second, so we need to multiply by 100 to convert to
1369                            milliseconds */
1370                         awt_multiclick_time = (int)Long.parseLong(multiclick_time_query) * 100;
1371                     } else {
1372                         awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME;
1373                     }
1374                 }
1375             } catch (NumberFormatException nf) {
1376                 awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME;
1377             } catch (NullPointerException npe) {
1378                 awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME;
1379             }
1380         } finally {
1381             awtUnlock();
1382         }
1383         if (awt_multiclick_time == 0) {
1384             awt_multiclick_time = AWT_MULTICLICK_DEFAULT_TIME;
1385         }
1386     }
1387 
1388     @Override
isFrameStateSupported(int state)1389     public boolean isFrameStateSupported(int state)
1390       throws HeadlessException
1391     {
1392         if (state == Frame.NORMAL || state == Frame.ICONIFIED) {
1393             return true;
1394         } else {
1395             return XWM.getWM().supportsExtendedState(state);
1396         }
1397     }
1398 
dumpPeers()1399     static void dumpPeers() {
1400         if (log.isLoggable(PlatformLogger.Level.FINE)) {
1401             log.fine("Mapped windows:");
1402             winMap.forEach((k, v) -> {
1403                 log.fine(k + "->" + v);
1404                 if (v instanceof XComponentPeer) {
1405                     Component target = (Component)((XComponentPeer)v).getTarget();
1406                     log.fine("\ttarget: " + target);
1407                 }
1408             });
1409 
1410             SunToolkit.dumpPeers(log);
1411 
1412             log.fine("Mapped special peers:");
1413             specialPeerMap.forEach((k, v) -> {
1414                 log.fine(k + "->" + v);
1415             });
1416 
1417             log.fine("Mapped dispatchers:");
1418             winToDispatcher.forEach((k, v) -> {
1419                 log.fine(k + "->" + v);
1420             });
1421         }
1422     }
1423 
1424     /* Protected with awt_lock. */
1425     private static boolean initialized;
1426     private static boolean timeStampUpdated;
1427     private static long timeStamp;
1428 
1429     private static final XEventDispatcher timeFetcher =
1430     new XEventDispatcher() {
1431             @Override
1432             public void dispatchEvent(XEvent ev) {
1433                 switch (ev.get_type()) {
1434                   case XConstants.PropertyNotify:
1435                       XPropertyEvent xpe = ev.get_xproperty();
1436 
1437                       awtLock();
1438                       try {
1439                           timeStamp = xpe.get_time();
1440                           timeStampUpdated = true;
1441                           awtLockNotifyAll();
1442                       } finally {
1443                           awtUnlock();
1444                       }
1445 
1446                       break;
1447                 }
1448             }
1449         };
1450 
1451     private static XAtom _XA_JAVA_TIME_PROPERTY_ATOM;
1452 
getCurrentServerTime()1453     static long getCurrentServerTime() {
1454         awtLock();
1455         try {
1456             try {
1457                 if (!initialized) {
1458                     XToolkit.addEventDispatcher(XBaseWindow.getXAWTRootWindow().getWindow(),
1459                                                 timeFetcher);
1460                     _XA_JAVA_TIME_PROPERTY_ATOM = XAtom.get("_SUNW_JAVA_AWT_TIME");
1461                     initialized = true;
1462                 }
1463                 timeStampUpdated = false;
1464                 XlibWrapper.XChangeProperty(XToolkit.getDisplay(),
1465                                             XBaseWindow.getXAWTRootWindow().getWindow(),
1466                                             _XA_JAVA_TIME_PROPERTY_ATOM.getAtom(), XAtom.XA_ATOM, 32,
1467                                             XConstants.PropModeAppend,
1468                                             0, 0);
1469                 XlibWrapper.XFlush(XToolkit.getDisplay());
1470 
1471                 if (isToolkitThread()) {
1472                     XEvent event = new XEvent();
1473                     try {
1474                         XlibWrapper.XWindowEvent(XToolkit.getDisplay(),
1475                                                  XBaseWindow.getXAWTRootWindow().getWindow(),
1476                                                  XConstants.PropertyChangeMask,
1477                                                  event.pData);
1478                         timeFetcher.dispatchEvent(event);
1479                     }
1480                     finally {
1481                         event.dispose();
1482                     }
1483                 }
1484                 else {
1485                     while (!timeStampUpdated) {
1486                         awtLockWait();
1487                     }
1488                 }
1489             } catch (InterruptedException ie) {
1490             // Note: the returned timeStamp can be incorrect in this case.
1491                 if (log.isLoggable(PlatformLogger.Level.FINE)) {
1492                     log.fine("Catched exception, timeStamp may not be correct (ie = " + ie + ")");
1493                 }
1494             }
1495         } finally {
1496             awtUnlock();
1497         }
1498         return timeStamp;
1499     }
1500     @Override
initializeDesktopProperties()1501     protected void initializeDesktopProperties() {
1502         desktopProperties.put("DnD.Autoscroll.initialDelay",
1503                               Integer.valueOf(50));
1504         desktopProperties.put("DnD.Autoscroll.interval",
1505                               Integer.valueOf(50));
1506         desktopProperties.put("DnD.Autoscroll.cursorHysteresis",
1507                               Integer.valueOf(5));
1508         desktopProperties.put("Shell.shellFolderManager",
1509                               "sun.awt.shell.ShellFolderManager");
1510         // Don't want to call getMultiClickTime() if we are headless
1511         if (!GraphicsEnvironment.isHeadless()) {
1512             desktopProperties.put("awt.multiClickInterval",
1513                                   Integer.valueOf(getMultiClickTime()));
1514             desktopProperties.put("awt.mouse.numButtons",
1515                                   Integer.valueOf(getNumberOfButtons()));
1516             if(SunGraphicsEnvironment.isUIScaleEnabled()) {
1517                 addPropertyChangeListener("gnome.Xft/DPI", evt ->
1518                                                      localEnv.displayChanged());
1519             }
1520         }
1521     }
1522 
1523     /**
1524      * This method runs through the XPointer and XExtendedPointer array.
1525      * XExtendedPointer has priority because on some systems XPointer
1526      * (which is assigned to the virtual pointer) reports the maximum
1527      * capabilities of the mouse pointer (i.e. 32 physical buttons).
1528      */
getNumberOfButtonsImpl()1529     private native int getNumberOfButtonsImpl();
1530 
1531     @Override
getNumberOfButtons()1532     public int getNumberOfButtons(){
1533         awtLock();
1534         try {
1535             if (numberOfButtons == 0) {
1536                 numberOfButtons = getNumberOfButtonsImpl();
1537                 numberOfButtons = (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons;
1538                 //4th and 5th buttons are for wheel and shouldn't be reported as buttons.
1539                 //If we have more than 3 physical buttons and a wheel, we report N-2 buttons.
1540                 //If we have 3 physical buttons and a wheel, we report 3 buttons.
1541                 //If we have 1,2,3 physical buttons, we report it as is i.e. 1,2 or 3 respectively.
1542                 if (numberOfButtons >=5) {
1543                     numberOfButtons -= 2;
1544                 } else if (numberOfButtons == 4 || numberOfButtons ==5){
1545                     numberOfButtons = 3;
1546                 }
1547             }
1548             //Assume don't have to re-query the number again and again.
1549             return numberOfButtons;
1550         } finally {
1551             awtUnlock();
1552         }
1553     }
1554 
getNumberOfButtonsForMask()1555     static int getNumberOfButtonsForMask() {
1556         return Math.min(XConstants.MAX_BUTTONS, ((SunToolkit) (Toolkit.getDefaultToolkit())).getNumberOfButtons());
1557     }
1558 
1559     private static final String prefix  = "DnD.Cursor.";
1560     private static final String postfix = ".32x32";
1561     private static final String dndPrefix  = "DnD.";
1562 
1563     @Override
lazilyLoadDesktopProperty(String name)1564     protected Object lazilyLoadDesktopProperty(String name) {
1565         if (name.startsWith(prefix)) {
1566             String cursorName = name.substring(prefix.length(), name.length()) + postfix;
1567 
1568             try {
1569                 return Cursor.getSystemCustomCursor(cursorName);
1570             } catch (AWTException awte) {
1571                 throw new RuntimeException("cannot load system cursor: " + cursorName, awte);
1572             }
1573         }
1574 
1575         if (name.equals("awt.dynamicLayoutSupported")) {
1576             return  Boolean.valueOf(isDynamicLayoutSupported());
1577         }
1578 
1579         if (initXSettingsIfNeeded(name)) {
1580             return desktopProperties.get(name);
1581         }
1582 
1583         return super.lazilyLoadDesktopProperty(name);
1584     }
1585 
1586     @Override
addPropertyChangeListener(String name, PropertyChangeListener pcl)1587     public synchronized void addPropertyChangeListener(String name, PropertyChangeListener pcl) {
1588         if (name == null) {
1589             // See JavaDoc for the Toolkit.addPropertyChangeListener() method
1590             return;
1591         }
1592         initXSettingsIfNeeded(name);
1593         super.addPropertyChangeListener(name, pcl);
1594     }
1595 
1596     /**
1597      * Initializes XAWTXSettings if a property for a given property name is provided by
1598      * XSettings and they are not initialized yet.
1599      *
1600      * @return true if the method has initialized XAWTXSettings.
1601      */
initXSettingsIfNeeded(final String propName)1602     private boolean initXSettingsIfNeeded(final String propName) {
1603         if (!loadedXSettings &&
1604             (propName.startsWith("gnome.") ||
1605              propName.equals(SunToolkit.DESKTOPFONTHINTS) ||
1606              propName.startsWith(dndPrefix)))
1607         {
1608             loadedXSettings = true;
1609             if (!GraphicsEnvironment.isHeadless()) {
1610                 loadXSettings();
1611                 /* If no desktop font hint could be retrieved, check for
1612                  * KDE running KWin and retrieve settings from fontconfig.
1613                  * If that isn't found let SunToolkit will see if there's a
1614                  * system property set by a user.
1615                  */
1616                 if (desktopProperties.get(SunToolkit.DESKTOPFONTHINTS) == null) {
1617                     if (XWM.isKDE2()) {
1618                         Object hint = FontConfigManager.getFontConfigAAHint();
1619                         if (hint != null) {
1620                             /* set the fontconfig/KDE property so that
1621                              * getDesktopHints() below will see it
1622                              * and set the public property.
1623                              */
1624                             desktopProperties.put(UNIXToolkit.FONTCONFIGAAHINT,
1625                                                   hint);
1626                         }
1627                     }
1628                     desktopProperties.put(SunToolkit.DESKTOPFONTHINTS,
1629                                           SunToolkit.getDesktopFontHints());
1630                 }
1631 
1632                 return true;
1633             }
1634         }
1635         return false;
1636     }
1637 
loadXSettings()1638     private void loadXSettings() {
1639        xs = new XAWTXSettings();
1640     }
1641 
1642     /**
1643      * Callback from the native side indicating some, or all, of the
1644      * desktop properties have changed and need to be reloaded.
1645      * {@code data} is the byte array directly from the x server and
1646      * may be in little endian format.
1647      * <p>
1648      * NB: This could be called from any thread if triggered by
1649      * {@code loadXSettings}.  It is called from the System EDT
1650      * if triggered by an XSETTINGS change.
1651      */
parseXSettings(int screen_XXX_ignored,Map<String, Object> updatedSettings)1652     void parseXSettings(int screen_XXX_ignored,Map<String, Object> updatedSettings) {
1653 
1654         if (updatedSettings == null || updatedSettings.isEmpty()) {
1655             return;
1656         }
1657 
1658         Iterator<Map.Entry<String, Object>> i = updatedSettings.entrySet().iterator();
1659         while (i.hasNext()) {
1660             Map.Entry<String, Object> e = i.next();
1661             String name = e.getKey();
1662 
1663             name = "gnome." + name;
1664             setDesktopProperty(name, e.getValue());
1665             if (log.isLoggable(PlatformLogger.Level.FINE)) {
1666                 log.fine("name = " + name + " value = " + e.getValue());
1667             }
1668 
1669             // XXX: we probably want to do something smarter.  In
1670             // particular, "Net" properties are of interest to the
1671             // "core" AWT itself.  E.g.
1672             //
1673             // Net/DndDragThreshold -> ???
1674             // Net/DoubleClickTime  -> awt.multiClickInterval
1675         }
1676 
1677         setDesktopProperty(SunToolkit.DESKTOPFONTHINTS,
1678                            SunToolkit.getDesktopFontHints());
1679 
1680         Integer dragThreshold = null;
1681         synchronized (this) {
1682             dragThreshold = (Integer)desktopProperties.get("gnome.Net/DndDragThreshold");
1683         }
1684         if (dragThreshold != null) {
1685             setDesktopProperty("DnD.gestureMotionThreshold", dragThreshold);
1686         }
1687 
1688     }
1689 
1690 
1691 
1692     static int altMask;
1693     static int metaMask;
1694     static int numLockMask;
1695     static int modeSwitchMask;
1696     static int modLockIsShiftLock;
1697 
1698     /* Like XKeysymToKeycode, but ensures that keysym is the primary
1699     * symbol on the keycode returned.  Returns zero otherwise.
1700     */
keysymToPrimaryKeycode(long sym)1701     static int keysymToPrimaryKeycode(long sym) {
1702         awtLock();
1703         try {
1704             int code = XlibWrapper.XKeysymToKeycode(getDisplay(), sym);
1705             if (code == 0) {
1706                 return 0;
1707             }
1708             long primary = XlibWrapper.XKeycodeToKeysym(getDisplay(), code, 0);
1709             if (sym != primary) {
1710                 return 0;
1711             }
1712             return code;
1713         } finally {
1714             awtUnlock();
1715         }
1716     }
getModifierState( int jkc )1717     static boolean getModifierState( int jkc ) {
1718         int iKeyMask = 0;
1719         long ks = XKeysym.javaKeycode2Keysym( jkc );
1720         int  kc = XlibWrapper.XKeysymToKeycode(getDisplay(), ks);
1721         if (kc == 0) {
1722             return false;
1723         }
1724         awtLock();
1725         try {
1726             XModifierKeymap modmap = new XModifierKeymap(
1727                  XlibWrapper.XGetModifierMapping(getDisplay()));
1728 
1729             int nkeys = modmap.get_max_keypermod();
1730 
1731             long map_ptr = modmap.get_modifiermap();
1732             for( int k = 0; k < 8; k++ ) {
1733                 for (int i = 0; i < nkeys; ++i) {
1734                     int keycode = Native.getUByte(map_ptr, k * nkeys + i);
1735                     if (keycode == 0) {
1736                         continue; // ignore zero keycode
1737                     }
1738                     if (kc == keycode) {
1739                         iKeyMask = 1 << k;
1740                         break;
1741                     }
1742                 }
1743                 if( iKeyMask != 0 ) {
1744                     break;
1745                 }
1746             }
1747             XlibWrapper.XFreeModifiermap(modmap.pData);
1748             if (iKeyMask == 0 ) {
1749                 return false;
1750             }
1751             // Now we know to which modifier is assigned the keycode
1752             // correspondent to the keysym correspondent to the java
1753             // keycode. We are going to check a state of this modifier.
1754             // If a modifier is a weird one, we cannot help it.
1755             long window = 0;
1756             try{
1757                 // get any application window
1758                 window = winMap.firstKey().longValue();
1759             }catch(NoSuchElementException nex) {
1760                 // get root window
1761                 window = getDefaultRootWindow();
1762             }
1763             boolean res = XlibWrapper.XQueryPointer(getDisplay(), window,
1764                                             XlibWrapper.larg1, //root
1765                                             XlibWrapper.larg2, //child
1766                                             XlibWrapper.larg3, //root_x
1767                                             XlibWrapper.larg4, //root_y
1768                                             XlibWrapper.larg5, //child_x
1769                                             XlibWrapper.larg6, //child_y
1770                                             XlibWrapper.larg7);//mask
1771             int mask = Native.getInt(XlibWrapper.larg7);
1772             return ((mask & iKeyMask) != 0);
1773         } finally {
1774             awtUnlock();
1775         }
1776     }
1777 
1778     /* Assign meaning - alt, meta, etc. - to X modifiers mod1 ... mod5.
1779      * Only consider primary symbols on keycodes attached to modifiers.
1780      */
setupModifierMap()1781     static void setupModifierMap() {
1782         final int metaL = keysymToPrimaryKeycode(XKeySymConstants.XK_Meta_L);
1783         final int metaR = keysymToPrimaryKeycode(XKeySymConstants.XK_Meta_R);
1784         final int altL = keysymToPrimaryKeycode(XKeySymConstants.XK_Alt_L);
1785         final int altR = keysymToPrimaryKeycode(XKeySymConstants.XK_Alt_R);
1786         final int numLock = keysymToPrimaryKeycode(XKeySymConstants.XK_Num_Lock);
1787         final int modeSwitch = keysymToPrimaryKeycode(XKeySymConstants.XK_Mode_switch);
1788         final int shiftLock = keysymToPrimaryKeycode(XKeySymConstants.XK_Shift_Lock);
1789         final int capsLock  = keysymToPrimaryKeycode(XKeySymConstants.XK_Caps_Lock);
1790 
1791         final int[] modmask = { XConstants.ShiftMask, XConstants.LockMask, XConstants.ControlMask, XConstants.Mod1Mask,
1792             XConstants.Mod2Mask, XConstants.Mod3Mask, XConstants.Mod4Mask, XConstants.Mod5Mask };
1793 
1794         log.fine("In setupModifierMap");
1795         awtLock();
1796         try {
1797             XModifierKeymap modmap = new XModifierKeymap(
1798                  XlibWrapper.XGetModifierMapping(getDisplay()));
1799 
1800             int nkeys = modmap.get_max_keypermod();
1801 
1802             long map_ptr = modmap.get_modifiermap();
1803 
1804             for (int modn = XConstants.Mod1MapIndex;
1805                  modn <= XConstants.Mod5MapIndex;
1806                  ++modn)
1807             {
1808                 for (int i = 0; i < nkeys; ++i) {
1809                     /* for each keycode attached to this modifier */
1810                     int keycode = Native.getUByte(map_ptr, modn * nkeys + i);
1811 
1812                     if (keycode == 0) {
1813                         break;
1814                     }
1815                     if (metaMask == 0 &&
1816                         (keycode == metaL || keycode == metaR))
1817                     {
1818                         metaMask = modmask[modn];
1819                         break;
1820                     }
1821                     if (altMask == 0 && (keycode == altL || keycode == altR)) {
1822                         altMask = modmask[modn];
1823                         break;
1824                     }
1825                     if (numLockMask == 0 && keycode == numLock) {
1826                         numLockMask = modmask[modn];
1827                         break;
1828                     }
1829                     if (modeSwitchMask == 0 && keycode == modeSwitch) {
1830                         modeSwitchMask = modmask[modn];
1831                         break;
1832                     }
1833                     continue;
1834                 }
1835             }
1836             modLockIsShiftLock = 0;
1837             for (int j = 0; j < nkeys; ++j) {
1838                 int keycode = Native.getUByte(map_ptr, XConstants.LockMapIndex * nkeys + j);
1839                 if (keycode == 0) {
1840                     break;
1841                 }
1842                 if (keycode == shiftLock) {
1843                     modLockIsShiftLock = 1;
1844                     break;
1845                 }
1846                 if (keycode == capsLock) {
1847                     break;
1848                 }
1849             }
1850             XlibWrapper.XFreeModifiermap(modmap.pData);
1851         } finally {
1852             awtUnlock();
1853         }
1854         if (log.isLoggable(PlatformLogger.Level.FINE)) {
1855             log.fine("metaMask = " + metaMask);
1856             log.fine("altMask = " + altMask);
1857             log.fine("numLockMask = " + numLockMask);
1858             log.fine("modeSwitchMask = " + modeSwitchMask);
1859             log.fine("modLockIsShiftLock = " + modLockIsShiftLock);
1860         }
1861     }
1862 
1863 
1864     private static SortedMap<Long, java.util.List<Runnable>> timeoutTasks;
1865 
1866     /**
1867      * Removed the task from the list of waiting-to-be called tasks.
1868      * If the task has been scheduled several times removes only first one.
1869      */
remove(Runnable task)1870     static void remove(Runnable task) {
1871         if (task == null) {
1872             throw new NullPointerException("task is null");
1873         }
1874         awtLock();
1875         try {
1876             if (timeoutTaskLog.isLoggable(PlatformLogger.Level.FINER)) {
1877                 timeoutTaskLog.finer("Removing task " + task);
1878             }
1879             if (timeoutTasks == null) {
1880                 if (timeoutTaskLog.isLoggable(PlatformLogger.Level.FINER)) {
1881                     timeoutTaskLog.finer("Task is not scheduled");
1882                 }
1883                 return;
1884             }
1885             Collection<java.util.List<Runnable>> values = timeoutTasks.values();
1886             Iterator<java.util.List<Runnable>> iter = values.iterator();
1887             while (iter.hasNext()) {
1888                 java.util.List<Runnable> list = iter.next();
1889                 boolean removed = false;
1890                 if (list.contains(task)) {
1891                     list.remove(task);
1892                     if (list.isEmpty()) {
1893                         iter.remove();
1894                     }
1895                     break;
1896                 }
1897             }
1898         } finally {
1899             awtUnlock();
1900         }
1901     }
1902 
wakeup_poll()1903     static native void wakeup_poll();
1904 
1905     /**
1906      * Registers a Runnable which {@code run()} method will be called
1907      * once on the toolkit thread when a specified interval of time elapses.
1908      *
1909      * @param task a Runnable which {@code run} method will be called
1910      *        on the toolkit thread when {@code interval} milliseconds
1911      *        elapse
1912      * @param interval an interal in milliseconds
1913      *
1914      * @throws NullPointerException if {@code task} is {@code null}
1915      * @throws IllegalArgumentException if {@code interval} is not positive
1916      */
schedule(Runnable task, long interval)1917     static void schedule(Runnable task, long interval) {
1918         if (task == null) {
1919             throw new NullPointerException("task is null");
1920         }
1921         if (interval <= 0) {
1922             throw new IllegalArgumentException("interval " + interval + " is not positive");
1923         }
1924 
1925         awtLock();
1926         try {
1927             if (timeoutTaskLog.isLoggable(PlatformLogger.Level.FINER)) {
1928                 timeoutTaskLog.finer("XToolkit.schedule(): current time={0}" +
1929                                      ";  interval={1}" +
1930                                      ";  task being added={2}" + ";  tasks before addition={3}",
1931                                      Long.valueOf(System.currentTimeMillis()), Long.valueOf(interval), task, timeoutTasks);
1932             }
1933 
1934             if (timeoutTasks == null) {
1935                 timeoutTasks = new TreeMap<>();
1936             }
1937 
1938             Long time = Long.valueOf(System.currentTimeMillis() + interval);
1939             java.util.List<Runnable> tasks = timeoutTasks.get(time);
1940             if (tasks == null) {
1941                 tasks = new ArrayList<>(1);
1942                 timeoutTasks.put(time, tasks);
1943             }
1944             tasks.add(task);
1945 
1946 
1947             if (timeoutTasks.get(timeoutTasks.firstKey()) == tasks && tasks.size() == 1) {
1948                 // Added task became first task - poll won't know
1949                 // about it so we need to wake it up
1950                 wakeup_poll();
1951             }
1952         }  finally {
1953             awtUnlock();
1954         }
1955     }
1956 
getNextTaskTime()1957     private long getNextTaskTime() {
1958         awtLock();
1959         try {
1960             if (timeoutTasks == null || timeoutTasks.isEmpty()) {
1961                 return -1L;
1962             }
1963             return timeoutTasks.firstKey();
1964         } finally {
1965             awtUnlock();
1966         }
1967     }
1968 
1969     /**
1970      * Executes mature timeout tasks registered with schedule().
1971      * Called from run() under awtLock.
1972      */
callTimeoutTasks()1973     private static void callTimeoutTasks() {
1974         if (timeoutTaskLog.isLoggable(PlatformLogger.Level.FINER)) {
1975             timeoutTaskLog.finer("XToolkit.callTimeoutTasks(): current time={0}" +
1976                                  ";  tasks={1}", Long.valueOf(System.currentTimeMillis()), timeoutTasks);
1977         }
1978 
1979         if (timeoutTasks == null || timeoutTasks.isEmpty()) {
1980             return;
1981         }
1982 
1983         Long currentTime = Long.valueOf(System.currentTimeMillis());
1984         Long time = timeoutTasks.firstKey();
1985 
1986         while (time.compareTo(currentTime) <= 0) {
1987             java.util.List<Runnable> tasks = timeoutTasks.remove(time);
1988 
1989             for (Iterator<Runnable> iter = tasks.iterator(); iter.hasNext();) {
1990                 Runnable task = iter.next();
1991 
1992                 if (timeoutTaskLog.isLoggable(PlatformLogger.Level.FINER)) {
1993                     timeoutTaskLog.finer("XToolkit.callTimeoutTasks(): current time={0}" +
1994                                          ";  about to run task={1}", Long.valueOf(currentTime), task);
1995                 }
1996 
1997                 try {
1998                     task.run();
1999                 } catch (ThreadDeath td) {
2000                     throw td;
2001                 } catch (Throwable thr) {
2002                     processException(thr);
2003                 }
2004             }
2005 
2006             if (timeoutTasks.isEmpty()) {
2007                 break;
2008             }
2009             time = timeoutTasks.firstKey();
2010         }
2011     }
2012 
isLeftMouseButton(MouseEvent me)2013     static boolean isLeftMouseButton(MouseEvent me) {
2014         switch (me.getID()) {
2015           case MouseEvent.MOUSE_PRESSED:
2016           case MouseEvent.MOUSE_RELEASED:
2017               return (me.getButton() == MouseEvent.BUTTON1);
2018           case MouseEvent.MOUSE_ENTERED:
2019           case MouseEvent.MOUSE_EXITED:
2020           case MouseEvent.MOUSE_CLICKED:
2021           case MouseEvent.MOUSE_DRAGGED:
2022               return ((me.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0);
2023         }
2024         return false;
2025     }
2026 
isRightMouseButton(MouseEvent me)2027     static boolean isRightMouseButton(MouseEvent me) {
2028         int numButtons = ((Integer)getDefaultToolkit().getDesktopProperty("awt.mouse.numButtons")).intValue();
2029         switch (me.getID()) {
2030           case MouseEvent.MOUSE_PRESSED:
2031           case MouseEvent.MOUSE_RELEASED:
2032               return ((numButtons == 2 && me.getButton() == MouseEvent.BUTTON2) ||
2033                        (numButtons > 2 && me.getButton() == MouseEvent.BUTTON3));
2034           case MouseEvent.MOUSE_ENTERED:
2035           case MouseEvent.MOUSE_EXITED:
2036           case MouseEvent.MOUSE_CLICKED:
2037           case MouseEvent.MOUSE_DRAGGED:
2038               return ((numButtons == 2 && (me.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK) != 0) ||
2039                       (numButtons > 2 && (me.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0));
2040         }
2041         return false;
2042     }
2043 
2044     static long reset_time_utc;
2045     static final long WRAP_TIME_MILLIS = 0x00000000FFFFFFFFL;
2046 
2047     /*
2048      * This function converts between the X server time (number of milliseconds
2049      * since the last server reset) and the UTC time for the 'when' field of an
2050      * InputEvent (or another event type with a timestamp).
2051      */
nowMillisUTC_offset(long server_offset)2052     static long nowMillisUTC_offset(long server_offset) {
2053         // ported from awt_util.c
2054         /*
2055          * Because Time is of type 'unsigned long', it is possible that Time will
2056          * never wrap when using 64-bit Xlib. However, if a 64-bit client
2057          * connects to a 32-bit server, I suspect the values will still wrap. So
2058          * we should not attempt to remove the wrap checking even if _LP64 is
2059          * true.
2060          */
2061 
2062         long current_time_utc = System.currentTimeMillis();
2063         if (log.isLoggable(PlatformLogger.Level.FINER)) {
2064             log.finer("reset_time=" + reset_time_utc + ", current_time=" + current_time_utc
2065                       + ", server_offset=" + server_offset + ", wrap_time=" + WRAP_TIME_MILLIS);
2066         }
2067 
2068         if ((current_time_utc - reset_time_utc) > WRAP_TIME_MILLIS) {
2069             reset_time_utc = System.currentTimeMillis() - getCurrentServerTime();
2070         }
2071 
2072         if (log.isLoggable(PlatformLogger.Level.FINER)) {
2073             log.finer("result = " + (reset_time_utc + server_offset));
2074         }
2075         return reset_time_utc + server_offset;
2076     }
2077 
2078     /**
2079      * @see sun.awt.SunToolkit#needsXEmbedImpl
2080      */
2081     @Override
needsXEmbedImpl()2082     protected boolean needsXEmbedImpl() {
2083         // XToolkit implements supports for XEmbed-client protocol and
2084         // requires the supports from the embedding host for it to work.
2085         return true;
2086     }
2087 
2088     @Override
isModalityTypeSupported(Dialog.ModalityType modalityType)2089     public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
2090         return (modalityType == null) ||
2091                (modalityType == Dialog.ModalityType.MODELESS) ||
2092                (modalityType == Dialog.ModalityType.DOCUMENT_MODAL) ||
2093                (modalityType == Dialog.ModalityType.APPLICATION_MODAL) ||
2094                (modalityType == Dialog.ModalityType.TOOLKIT_MODAL);
2095     }
2096 
2097     @Override
isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType)2098     public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
2099         return (exclusionType == null) ||
2100                (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE) ||
2101                (exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) ||
2102                (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
2103     }
2104 
getEventQueue(Object target)2105     static EventQueue getEventQueue(Object target) {
2106         AppContext appContext = targetToAppContext(target);
2107         if (appContext != null) {
2108             return (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
2109         }
2110         return null;
2111     }
2112 
removeSourceEvents(EventQueue queue, Object source, boolean removeAllEvents)2113     static void removeSourceEvents(EventQueue queue,
2114                                    Object source,
2115                                    boolean removeAllEvents) {
2116         AWTAccessor.getEventQueueAccessor()
2117             .removeSourceEvents(queue, source, removeAllEvents);
2118     }
2119 
2120     @Override
isAlwaysOnTopSupported()2121     public boolean isAlwaysOnTopSupported() {
2122         for (XLayerProtocol proto : XWM.getWM().getProtocols(XLayerProtocol.class)) {
2123             if (proto.supportsLayer(XLayerProtocol.LAYER_ALWAYS_ON_TOP)) {
2124                 return true;
2125             }
2126         }
2127         return false;
2128     }
2129 
2130     @Override
useBufferPerWindow()2131     public boolean useBufferPerWindow() {
2132         return XToolkit.getBackingStoreType() == XConstants.NotUseful;
2133     }
2134 
2135     /**
2136      * Returns one of XConstants: NotUseful, WhenMapped or Always.
2137      * If backing store is not available on at least one screen, or
2138      * the string system property "sun.awt.backingStore" is neither "Always"
2139      * nor "WhenMapped", then the method returns XConstants.NotUseful.
2140      * Otherwise, if the system property "sun.awt.backingStore" is "WhenMapped",
2141      * then the method returns XConstants.WhenMapped.
2142      * Otherwise (i.e., if the system property "sun.awt.backingStore" is "Always"),
2143      * the method returns XConstants.Always.
2144      */
getBackingStoreType()2145     static int getBackingStoreType() {
2146         return backingStoreType;
2147     }
2148 
setBackingStoreType()2149     private static void setBackingStoreType() {
2150         String prop = AccessController.doPrivileged(
2151                 new sun.security.action.GetPropertyAction("sun.awt.backingStore"));
2152 
2153         if (prop == null) {
2154             backingStoreType = XConstants.NotUseful;
2155             if (backingStoreLog.isLoggable(PlatformLogger.Level.CONFIG)) {
2156                 backingStoreLog.config("The system property sun.awt.backingStore is not set" +
2157                                        ", by default backingStore=NotUseful");
2158             }
2159             return;
2160         }
2161 
2162         if (backingStoreLog.isLoggable(PlatformLogger.Level.CONFIG)) {
2163             backingStoreLog.config("The system property sun.awt.backingStore is " + prop);
2164         }
2165         prop = prop.toLowerCase();
2166         if (prop.equals("always")) {
2167             backingStoreType = XConstants.Always;
2168         } else if (prop.equals("whenmapped")) {
2169             backingStoreType = XConstants.WhenMapped;
2170         } else {
2171             backingStoreType = XConstants.NotUseful;
2172         }
2173 
2174         if (backingStoreLog.isLoggable(PlatformLogger.Level.CONFIG)) {
2175             backingStoreLog.config("backingStore(as provided by the system property)=" +
2176                                    ( backingStoreType == XConstants.NotUseful ? "NotUseful"
2177                                      : backingStoreType == XConstants.WhenMapped ?
2178                                      "WhenMapped" : "Always") );
2179         }
2180 
2181         awtLock();
2182         try {
2183             int screenCount = XlibWrapper.ScreenCount(getDisplay());
2184             for (int i = 0; i < screenCount; i++) {
2185                 if (XlibWrapper.DoesBackingStore(XlibWrapper.ScreenOfDisplay(getDisplay(), i))
2186                         == XConstants.NotUseful) {
2187                     backingStoreType = XConstants.NotUseful;
2188 
2189                     if (backingStoreLog.isLoggable(PlatformLogger.Level.CONFIG)) {
2190                         backingStoreLog.config("Backing store is not available on the screen " +
2191                                                i + ", backingStore=NotUseful");
2192                     }
2193 
2194                     return;
2195                 }
2196             }
2197         } finally {
2198             awtUnlock();
2199         }
2200     }
2201 
2202     /**
2203      * One of XConstants: NotUseful, WhenMapped or Always.
2204      */
2205     private static int backingStoreType;
2206 
2207     static final int XSUN_KP_BEHAVIOR = 1;
2208     static final int XORG_KP_BEHAVIOR = 2;
2209     static final int    IS_SUN_KEYBOARD = 1;
2210     static final int IS_NONSUN_KEYBOARD = 2;
2211     static final int    IS_KANA_KEYBOARD = 1;
2212     static final int IS_NONKANA_KEYBOARD = 2;
2213 
2214 
2215     static int     awt_IsXsunKPBehavior = 0;
2216     static boolean awt_UseXKB         = false;
2217     static boolean awt_UseXKB_Calls   = false;
2218     static int     awt_XKBBaseEventCode = 0;
2219     static int     awt_XKBEffectiveGroup = 0; // so far, I don't use it leaving all calculations
2220                                               // to XkbTranslateKeyCode
2221     static long    awt_XKBDescPtr     = 0;
2222 
2223     /**
2224      * Check for Xsun convention regarding numpad keys.
2225      * Xsun and some other servers (i.e. derived from Xsun)
2226      * under certain conditions process numpad keys unlike Xorg.
2227      */
isXsunKPBehavior()2228     static boolean isXsunKPBehavior() {
2229         awtLock();
2230         try {
2231             if( awt_IsXsunKPBehavior == 0 ) {
2232                 if( XlibWrapper.IsXsunKPBehavior(getDisplay()) ) {
2233                     awt_IsXsunKPBehavior = XSUN_KP_BEHAVIOR;
2234                 }else{
2235                     awt_IsXsunKPBehavior = XORG_KP_BEHAVIOR;
2236                 }
2237             }
2238             return awt_IsXsunKPBehavior == XSUN_KP_BEHAVIOR ? true : false;
2239         } finally {
2240             awtUnlock();
2241         }
2242     }
2243 
2244     static int  sunOrNotKeyboard = 0;
2245     static int kanaOrNotKeyboard = 0;
resetKeyboardSniffer()2246     static void resetKeyboardSniffer() {
2247         sunOrNotKeyboard  = 0;
2248         kanaOrNotKeyboard = 0;
2249     }
isSunKeyboard()2250     static boolean isSunKeyboard() {
2251         if( sunOrNotKeyboard == 0 ) {
2252             if( XlibWrapper.IsSunKeyboard( getDisplay() )) {
2253                 sunOrNotKeyboard = IS_SUN_KEYBOARD;
2254             }else{
2255                 sunOrNotKeyboard = IS_NONSUN_KEYBOARD;
2256             }
2257         }
2258         return (sunOrNotKeyboard == IS_SUN_KEYBOARD);
2259     }
isKanaKeyboard()2260     static boolean isKanaKeyboard() {
2261         if( kanaOrNotKeyboard == 0 ) {
2262             if( XlibWrapper.IsKanaKeyboard( getDisplay() )) {
2263                 kanaOrNotKeyboard = IS_KANA_KEYBOARD;
2264             }else{
2265                 kanaOrNotKeyboard = IS_NONKANA_KEYBOARD;
2266             }
2267         }
2268         return (kanaOrNotKeyboard == IS_KANA_KEYBOARD);
2269     }
isXKBenabled()2270     static boolean isXKBenabled() {
2271         awtLock();
2272         try {
2273             return awt_UseXKB;
2274         } finally {
2275             awtUnlock();
2276         }
2277     }
2278 
2279     /**
2280       Query XKEYBOARD extension.
2281       If possible, initialize xkb library.
2282     */
tryXKB()2283     static boolean tryXKB() {
2284         awtLock();
2285         try {
2286             String name = "XKEYBOARD";
2287             // First, if there is extension at all.
2288             awt_UseXKB = XlibWrapper.XQueryExtension( getDisplay(), name, XlibWrapper.larg1, XlibWrapper.larg2, XlibWrapper.larg3);
2289             if( awt_UseXKB ) {
2290                 // There is a keyboard extension. Check if a client library is compatible.
2291                 // If not, don't use xkb calls.
2292                 // In this case we still may be Xkb-capable application.
2293                 awt_UseXKB_Calls = XlibWrapper.XkbLibraryVersion( XlibWrapper.larg1, XlibWrapper.larg2);
2294                 if( awt_UseXKB_Calls ) {
2295                     awt_UseXKB_Calls = XlibWrapper.XkbQueryExtension( getDisplay(),  XlibWrapper.larg1, XlibWrapper.larg2,
2296                                      XlibWrapper.larg3, XlibWrapper.larg4, XlibWrapper.larg5);
2297                     if( awt_UseXKB_Calls ) {
2298                         awt_XKBBaseEventCode = Native.getInt(XlibWrapper.larg2);
2299                         XlibWrapper.XkbSelectEvents (getDisplay(),
2300                                          XConstants.XkbUseCoreKbd,
2301                                          XConstants.XkbNewKeyboardNotifyMask |
2302                                                  XConstants.XkbMapNotifyMask ,//|
2303                                                  //XConstants.XkbStateNotifyMask,
2304                                          XConstants.XkbNewKeyboardNotifyMask |
2305                                                  XConstants.XkbMapNotifyMask );//|
2306                                                  //XConstants.XkbStateNotifyMask);
2307 
2308                         XlibWrapper.XkbSelectEventDetails(getDisplay(), XConstants.XkbUseCoreKbd,
2309                                                      XConstants.XkbStateNotify,
2310                                                      XConstants.XkbGroupStateMask,
2311                                                      XConstants.XkbGroupStateMask);
2312                                                      //XXX ? XkbGroupLockMask last, XkbAllStateComponentsMask before last?
2313                         awt_XKBDescPtr = XlibWrapper.XkbGetMap(getDisplay(),
2314                                                      XConstants.XkbKeyTypesMask    |
2315                                                      XConstants.XkbKeySymsMask     |
2316                                                      XConstants.XkbModifierMapMask |
2317                                                      XConstants.XkbVirtualModsMask,
2318                                                      XConstants.XkbUseCoreKbd);
2319 
2320                         XlibWrapper.XkbSetDetectableAutoRepeat(getDisplay(), true);
2321                     }
2322                 }
2323             }
2324             return awt_UseXKB;
2325         } finally {
2326             awtUnlock();
2327         }
2328     }
canUseXKBCalls()2329     static boolean canUseXKBCalls() {
2330         awtLock();
2331         try {
2332             return awt_UseXKB_Calls;
2333         } finally {
2334             awtUnlock();
2335         }
2336     }
getXKBEffectiveGroup()2337     static int getXKBEffectiveGroup() {
2338         awtLock();
2339         try {
2340             return awt_XKBEffectiveGroup;
2341         } finally {
2342             awtUnlock();
2343         }
2344     }
getXKBBaseEventCode()2345     static int getXKBBaseEventCode() {
2346         awtLock();
2347         try {
2348             return awt_XKBBaseEventCode;
2349         } finally {
2350             awtUnlock();
2351         }
2352     }
getXKBKbdDesc()2353     static long getXKBKbdDesc() {
2354         awtLock();
2355         try {
2356             return awt_XKBDescPtr;
2357         } finally {
2358             awtUnlock();
2359         }
2360     }
freeXKB()2361     void freeXKB() {
2362         awtLock();
2363         try {
2364             if (awt_UseXKB_Calls && awt_XKBDescPtr != 0) {
2365                 XlibWrapper.XkbFreeKeyboard(awt_XKBDescPtr, 0xFF, true);
2366                 awt_XKBDescPtr = 0;
2367             }
2368         } finally {
2369             awtUnlock();
2370         }
2371     }
processXkbChanges(XEvent ev)2372     private void processXkbChanges(XEvent ev) {
2373         // mapping change --> refresh kbd map
2374         // state change --> get a new effective group; do I really need it
2375         //  or that should be left for XkbTranslateKeyCode?
2376         XkbEvent xke = new XkbEvent( ev.getPData() );
2377         int xkb_type = xke.get_any().get_xkb_type();
2378         switch( xkb_type ) {
2379             case XConstants.XkbNewKeyboardNotify :
2380                  if( awt_XKBDescPtr != 0 ) {
2381                      freeXKB();
2382                  }
2383                  awt_XKBDescPtr = XlibWrapper.XkbGetMap(getDisplay(),
2384                                               XConstants.XkbKeyTypesMask    |
2385                                               XConstants.XkbKeySymsMask     |
2386                                               XConstants.XkbModifierMapMask |
2387                                               XConstants.XkbVirtualModsMask,
2388                                               XConstants.XkbUseCoreKbd);
2389                  //System.out.println("XkbNewKeyboard:"+(xke.get_new_kbd()));
2390                  break;
2391             case XConstants.XkbMapNotify :
2392                  if (awt_XKBDescPtr != 0) {
2393                     //TODO: provide a simple unit test.
2394                     XlibWrapper.XkbGetUpdatedMap(getDisplay(),
2395                                                  XConstants.XkbKeyTypesMask    |
2396                                                  XConstants.XkbKeySymsMask     |
2397                                                  XConstants.XkbModifierMapMask |
2398                                                  XConstants.XkbVirtualModsMask,
2399                                                  awt_XKBDescPtr);
2400                  }
2401                 //System.out.println("XkbMap:"+(xke.get_map()));
2402                  break;
2403             case XConstants.XkbStateNotify :
2404                  // May use it later e.g. to obtain an effective group etc.
2405                  //System.out.println("XkbState:"+(xke.get_state()));
2406                  break;
2407             default:
2408                  //System.out.println("XkbEvent of xkb_type "+xkb_type);
2409                  break;
2410         }
2411     }
2412 
2413     private static long eventNumber;
getEventNumber()2414     public static long getEventNumber() {
2415         awtLock();
2416         try {
2417             return eventNumber;
2418         } finally {
2419             awtUnlock();
2420         }
2421     }
2422 
2423     private static XEventDispatcher oops_waiter;
2424     private static boolean oops_updated;
2425     private static int oops_position = 0;
2426 
2427     /**
2428      * @inheritDoc
2429      */
2430     @Override
syncNativeQueue(final long timeout)2431     protected boolean syncNativeQueue(final long timeout) {
2432         if (timeout <= 0) {
2433             return false;
2434         }
2435         XBaseWindow win = XBaseWindow.getXAWTRootWindow();
2436 
2437         if (oops_waiter == null) {
2438             oops_waiter = new XEventDispatcher() {
2439                     @Override
2440                     public void dispatchEvent(XEvent e) {
2441                         if (e.get_type() == XConstants.ConfigureNotify) {
2442                             // OOPS ConfigureNotify event catched
2443                             oops_updated = true;
2444                             awtLockNotifyAll();
2445                         }
2446                     }
2447                 };
2448         }
2449 
2450         awtLock();
2451         try {
2452             addEventDispatcher(win.getWindow(), oops_waiter);
2453 
2454             oops_updated = false;
2455             long event_number = getEventNumber();
2456             // Generate OOPS ConfigureNotify event
2457             XlibWrapper.XMoveWindow(getDisplay(), win.getWindow(),
2458                                     win.scaleUp(++oops_position), 0);
2459             // Change win position each time to avoid system optimization
2460             if (oops_position > 50) {
2461                 oops_position = 0;
2462             }
2463 
2464             XSync();
2465 
2466             eventLog.finer("Generated OOPS ConfigureNotify event");
2467 
2468             long start = System.currentTimeMillis();
2469             while (!oops_updated) {
2470                 try {
2471                     // Wait for OOPS ConfigureNotify event
2472                     awtLockWait(timeout);
2473                 } catch (InterruptedException e) {
2474                     throw new RuntimeException(e);
2475                 }
2476                 // This "while" is a protection from spurious
2477                 // wake-ups.  However, we shouldn't wait for too long
2478                 if ((System.currentTimeMillis() - start > timeout) && timeout >= 0) {
2479                     throw new OperationTimedOut(Long.toString(System.currentTimeMillis() - start));
2480                 }
2481             }
2482             // Don't take into account OOPS ConfigureNotify event
2483             return getEventNumber() - event_number > 1;
2484         } finally {
2485             removeEventDispatcher(win.getWindow(), oops_waiter);
2486             eventLog.finer("Exiting syncNativeQueue");
2487             awtUnlock();
2488         }
2489     }
2490     @Override
grab(Window w)2491     public void grab(Window w) {
2492         final Object peer = AWTAccessor.getComponentAccessor().getPeer(w);
2493         if (peer != null) {
2494             ((XWindowPeer) peer).setGrab(true);
2495         }
2496     }
2497 
2498     @Override
ungrab(Window w)2499     public void ungrab(Window w) {
2500         final Object peer = AWTAccessor.getComponentAccessor().getPeer(w);
2501         if (peer != null) {
2502             ((XWindowPeer) peer).setGrab(false);
2503         }
2504     }
2505     /**
2506      * Returns if the java.awt.Desktop class is supported on the current
2507      * desktop.
2508      * <p>
2509      * The methods of java.awt.Desktop class are supported on the Gnome desktop.
2510      * Check if the running desktop is Gnome by checking the window manager.
2511      */
2512     @Override
isDesktopSupported()2513     public boolean isDesktopSupported(){
2514         return XDesktopPeer.isDesktopSupported();
2515     }
2516 
2517     @Override
createDesktopPeer(Desktop target)2518     public DesktopPeer createDesktopPeer(Desktop target){
2519         return new XDesktopPeer();
2520     }
2521 
2522     @Override
isTaskbarSupported()2523     public boolean isTaskbarSupported(){
2524         return XTaskbarPeer.isTaskbarSupported();
2525     }
2526 
2527     @Override
createTaskbarPeer(Taskbar target)2528     public TaskbarPeer createTaskbarPeer(Taskbar target){
2529         return new XTaskbarPeer();
2530     }
2531 
2532     @Override
areExtraMouseButtonsEnabled()2533     public boolean areExtraMouseButtonsEnabled() throws HeadlessException {
2534         return areExtraMouseButtonsEnabled;
2535     }
2536 
2537     @Override
isWindowOpacitySupported()2538     public boolean isWindowOpacitySupported() {
2539         XNETProtocol net_protocol = XWM.getWM().getNETProtocol();
2540 
2541         if (net_protocol == null) {
2542             return false;
2543         }
2544 
2545         return net_protocol.doOpacityProtocol();
2546     }
2547 
2548     @Override
isWindowShapingSupported()2549     public boolean isWindowShapingSupported() {
2550         return XlibUtil.isShapingSupported();
2551     }
2552 
2553     @Override
isWindowTranslucencySupported()2554     public boolean isWindowTranslucencySupported() {
2555         //NOTE: it may not be supported. The actual check is being performed
2556         //      at java.awt.GraphicsDevice. In X11 we need to check
2557         //      whether there's any translucency-capable GC available.
2558         return true;
2559     }
2560 
2561     @Override
isTranslucencyCapable(GraphicsConfiguration gc)2562     public boolean isTranslucencyCapable(GraphicsConfiguration gc) {
2563         if (!(gc instanceof X11GraphicsConfig)) {
2564             return false;
2565         }
2566         return ((X11GraphicsConfig)gc).isTranslucencyCapable();
2567     }
2568 
2569     /**
2570      * Returns the value of "sun.awt.disablegrab" property. Default
2571      * value is {@code false}.
2572      */
getSunAwtDisableGrab()2573     public static boolean getSunAwtDisableGrab() {
2574         return AccessController.doPrivileged(new GetBooleanAction("sun.awt.disablegrab"));
2575     }
2576 }
2577