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