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