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