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