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