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