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