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