1 /*
   2  * Copyright 1995-2009 Sun Microsystems, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 
  26 package sun.awt.motif;
  27 
  28 import java.awt.*;
  29 import java.awt.im.InputMethodHighlight;
  30 import java.awt.im.spi.InputMethodDescriptor;
  31 import java.awt.image.*;
  32 import java.awt.peer.*;
  33 import java.awt.datatransfer.Clipboard;
  34 import java.awt.event.*;
  35 import java.lang.reflect.*;
  36 import java.lang.Math;
  37 import java.io.*;
  38 import java.security.AccessController;
  39 import java.security.PrivilegedAction;
  40 import java.security.PrivilegedActionException;
  41 import java.security.PrivilegedExceptionAction;
  42 
  43 import java.util.Properties;
  44 import java.util.Map;
  45 import java.util.Iterator;
  46 import java.util.logging.*;
  47 
  48 import sun.awt.AppContext;
  49 import sun.awt.AWTAutoShutdown;
  50 import sun.awt.SunToolkit;
  51 import sun.awt.UNIXToolkit;
  52 import sun.awt.GlobalCursorManager;
  53 import sun.awt.datatransfer.DataTransferer;
  54 
  55 import java.awt.dnd.DragSource;
  56 import java.awt.dnd.DragGestureListener;
  57 import java.awt.dnd.DragGestureEvent;
  58 import java.awt.dnd.DragGestureRecognizer;
  59 import java.awt.dnd.MouseDragGestureRecognizer;
  60 import java.awt.dnd.InvalidDnDOperationException;
  61 import java.awt.dnd.peer.DragSourceContextPeer;
  62 
  63 //import sun.awt.motif.MInputMethod;
  64 import sun.awt.X11GraphicsConfig;
  65 import sun.awt.X11GraphicsEnvironment;
  66 import sun.awt.XSettings;
  67 
  68 //import sun.awt.motif.MDragSourceContextPeer;
  69 
  70 import sun.print.PrintJob2D;
  71 
  72 import sun.misc.PerformanceLogger;
  73 import sun.misc.Unsafe;
  74 
  75 import sun.security.action.GetBooleanAction;
  76 
  77 public class MToolkit extends UNIXToolkit implements Runnable {
  78 
  79     private static final Logger log = Logger.getLogger("sun.awt.motif.MToolkit");
  80 
  81     // the system clipboard - CLIPBOARD selection
  82     //X11Clipboard clipboard;
  83     // the system selection - PRIMARY selection
  84     //X11Clipboard selection;
  85 
  86     // Dynamic Layout Resize client code setting
  87     protected static boolean dynamicLayoutSetting = false;
  88 
  89     /**
  90      * True when the x settings have been loaded.
  91      */
  92     private boolean loadedXSettings;
  93 
  94     /**
  95      * XSETTINGS for the default screen.
  96      * <p>
  97      * <strong>XXX:</strong> see <code>MToolkit.parseXSettings</code>
  98      * and <code>awt_xsettings_update</code> in
  99      * <samp>awt_MToolkit.c</samp>
 100      */
 101     private XSettings xs;
 102 
 103     /*
 104      * Note: The MToolkit object depends on the static initializer
 105      * of X11GraphicsEnvironment to initialize the connection to
 106      * the X11 server.
 107      */
 108     static final X11GraphicsConfig config;
 109 
 110     private static final boolean motifdnd;
 111 
 112     static {
 113         if (GraphicsEnvironment.isHeadless()) {
 114             config = null;
 115         } else {
 116             config = (X11GraphicsConfig) (GraphicsEnvironment.
 117                              getLocalGraphicsEnvironment().
 118                              getDefaultScreenDevice().
 119                              getDefaultConfiguration());
 120         }
 121 
 122         /* Add font properties font directories to the X11 font path.
 123          * Its called here *after* the X connection has been initialised
 124          * and when we know that MToolkit is the one that will be used,
 125          * since XToolkit doesn't need the X11 font path set
 126          */
 127         X11GraphicsEnvironment.setNativeFontPath();
 128 
 129         motifdnd = ((Boolean)java.security.AccessController.doPrivileged(
 130             new GetBooleanAction("awt.dnd.motifdnd"))).booleanValue();
 131     }
 132 
 133     //public static final String DATA_TRANSFERER_CLASS_NAME = "sun.awt.motif.MDataTransferer";
 134 
 135     public MToolkit() {
 136         super();
 137         if (PerformanceLogger.loggingEnabled()) {
 138             PerformanceLogger.setTime("MToolkit construction");
 139         }
 140         if (!GraphicsEnvironment.isHeadless()) {
 141             String mainClassName = null;
 142 
 143             StackTraceElement trace[] = (new Throwable()).getStackTrace();
 144             int bottom = trace.length - 1;
 145             if (bottom >= 0) {
 146                 mainClassName = trace[bottom].getClassName();
 147             }
 148             if (mainClassName == null || mainClassName.equals("")) {
 149                 mainClassName = "AWT";
 150             }
 151 
 152             init(mainClassName);
 153             //SunToolkit.setDataTransfererClassName(DATA_TRANSFERER_CLASS_NAME);
 154 
 155             Thread toolkitThread = new Thread(this, "AWT-Motif");
 156             toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);
 157             toolkitThread.setDaemon(true);
 158             ThreadGroup mainTG = (ThreadGroup)AccessController.doPrivileged(
 159                 new PrivilegedAction() {
 160                     public Object run() {
 161                         ThreadGroup currentTG =
 162                             Thread.currentThread().getThreadGroup();
 163                         ThreadGroup parentTG = currentTG.getParent();
 164                         while (parentTG != null) {
 165                             currentTG = parentTG;
 166                             parentTG = currentTG.getParent();
 167                         }
 168                         return currentTG;
 169                     }
 170             });
 171 
 172             Runtime.getRuntime().addShutdownHook(
 173                 new Thread(mainTG, new Runnable() {
 174                     public void run() {
 175                         shutdown();
 176                     }
 177                 }, "Shutdown-Thread")
 178             );
 179 
 180             /*
 181              * Fix for 4701990.
 182              * AWTAutoShutdown state must be changed before the toolkit thread
 183              * starts to avoid race condition.
 184              */
 185             AWTAutoShutdown.notifyToolkitThreadBusy();
 186 
 187             toolkitThread.start();
 188         }
 189     }
 190 
 191     public native void init(String mainClassName);
 192     public native void run();
 193     private native void shutdown();
 194 
 195     /*
 196      * Create peer objects.
 197      */
 198 
 199     public ButtonPeer createButton(Button target) {
 200         //ButtonPeer peer = new MButtonPeer(target);
 201         //targetCreatedPeer(target, peer);
 202         //return peer;
 203         return null;
 204     }
 205 
 206     public TextFieldPeer createTextField(TextField target) {
 207         //TextFieldPeer peer = new MTextFieldPeer(target);
 208         //targetCreatedPeer(target, peer);
 209         //return peer;
 210         return null;
 211     }
 212 
 213     public LabelPeer createLabel(Label target) {
 214         //LabelPeer peer = new MLabelPeer(target);
 215         //targetCreatedPeer(target, peer);
 216         //return peer;
 217         return null;
 218     }
 219 
 220     public ListPeer createList(List target) {
 221         //ListPeer peer = new MListPeer(target);
 222         //targetCreatedPeer(target, peer);
 223         //return peer;
 224         return null;
 225     }
 226 
 227     public CheckboxPeer createCheckbox(Checkbox target) {
 228         //CheckboxPeer peer = new MCheckboxPeer(target);
 229         //targetCreatedPeer(target, peer);
 230         //return peer;
 231         return null;
 232     }
 233 
 234     public ScrollbarPeer createScrollbar(Scrollbar target) {
 235         //ScrollbarPeer peer = new MScrollbarPeer(target);
 236         //targetCreatedPeer(target, peer);
 237         //return peer;
 238         return null;
 239     }
 240 
 241     public ScrollPanePeer createScrollPane(ScrollPane target) {
 242         //ScrollPanePeer peer = new MScrollPanePeer(target);
 243         //targetCreatedPeer(target, peer);
 244         //return peer;
 245         return null;
 246     }
 247 
 248     public TextAreaPeer createTextArea(TextArea target) {
 249         //TextAreaPeer peer = new MTextAreaPeer(target);
 250         //targetCreatedPeer(target, peer);
 251         //return peer;
 252         return null;
 253     }
 254 
 255     public ChoicePeer createChoice(Choice target) {
 256         //ChoicePeer peer = new MChoicePeer(target);
 257         //targetCreatedPeer(target, peer);
 258         //return peer;
 259         return null;
 260     }
 261 
 262     public FramePeer  createFrame(Frame target) {
 263         //FramePeer peer = new MFramePeer(target);
 264         //targetCreatedPeer(target, peer);
 265         //return peer;
 266         return null;
 267     }
 268 
 269     public CanvasPeer createCanvas(Canvas target) {
 270         //CanvasPeer peer = (isXEmbedServerRequested() ? new MEmbedCanvasPeer(target) : new MCanvasPeer(target));
 271         //targetCreatedPeer(target, peer);
 272         //return peer;
 273         return null;
 274     }
 275 
 276     public PanelPeer createPanel(Panel target) {
 277         //PanelPeer peer = new MPanelPeer(target);
 278         //targetCreatedPeer(target, peer);
 279         //return peer;
 280         return null;
 281     }
 282 
 283     public WindowPeer createWindow(Window target) {
 284         //WindowPeer peer = new MWindowPeer(target);
 285         //targetCreatedPeer(target, peer);
 286         //return peer;
 287         return null;
 288     }
 289 
 290     public DialogPeer createDialog(Dialog target) {
 291         //DialogPeer peer = new MDialogPeer(target);
 292         //targetCreatedPeer(target, peer);
 293         //return peer;
 294         return null;
 295     }
 296 
 297     public FileDialogPeer createFileDialog(FileDialog target) {
 298         //FileDialogPeer peer = new MFileDialogPeer(target);
 299         //targetCreatedPeer(target, peer);
 300         //return peer;
 301         return null;
 302     }
 303 
 304     public MenuBarPeer createMenuBar(MenuBar target) {
 305         //MenuBarPeer peer = new MMenuBarPeer(target);
 306         //targetCreatedPeer(target, peer);
 307         //return peer;
 308         return null;
 309     }
 310 
 311     public MenuPeer createMenu(Menu target) {
 312         //MenuPeer peer = new MMenuPeer(target);
 313         //targetCreatedPeer(target, peer);
 314         //return peer;
 315         return null;
 316     }
 317 
 318     public PopupMenuPeer createPopupMenu(PopupMenu target) {
 319         //PopupMenuPeer peer = new MPopupMenuPeer(target);
 320         //targetCreatedPeer(target, peer);
 321         //return peer;
 322         return null;
 323     }
 324 
 325     public MenuItemPeer createMenuItem(MenuItem target) {
 326         //MenuItemPeer peer = new MMenuItemPeer(target);
 327         //targetCreatedPeer(target, peer);
 328         //return peer;
 329         return null;
 330     }
 331 
 332     public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) {
 333         //CheckboxMenuItemPeer peer = new MCheckboxMenuItemPeer(target);
 334         //targetCreatedPeer(target, peer);
 335         //return peer;
 336         return null;
 337     }
 338 
 339     public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
 340         return null;
 341     }
 342 
 343     //public MEmbeddedFramePeer createEmbeddedFrame(MEmbeddedFrame target)
 344     //{
 345         //MEmbeddedFramePeer peer = new MEmbeddedFramePeer(target);
 346         //targetCreatedPeer(target, peer);
 347         //return peer;
 348     //    return null;
 349     //}
 350 
 351 
 352     public FontPeer getFontPeer(String name, int style){
 353         return new MFontPeer(name, style);
 354     }
 355 
 356     /*
 357      * On X, support for dynamic layout on resizing is governed by the
 358      * window manager.  If the window manager supports it, it happens
 359      * automatically.  The setter method for this property is
 360      * irrelevant on X.
 361      */
 362     public void setDynamicLayout(boolean b) {
 363         dynamicLayoutSetting = b;
 364     }
 365 
 366     protected boolean isDynamicLayoutSet() {
 367         return dynamicLayoutSetting;
 368     }
 369 
 370     /* Called from isDynamicLayoutActive() and from
 371      * lazilyLoadDynamicLayoutSupportedProperty()
 372      */
 373     protected native boolean isDynamicLayoutSupportedNative();
 374 
 375     public boolean isDynamicLayoutActive() {
 376         return isDynamicLayoutSupportedNative();
 377     }
 378 
 379     public native boolean isFrameStateSupported(int state);
 380 
 381     public TrayIconPeer createTrayIcon(TrayIcon target) throws HeadlessException {
 382         return null;
 383     }
 384 
 385     public SystemTrayPeer createSystemTray(SystemTray target) throws HeadlessException {
 386         return null;
 387     }
 388 
 389     public boolean isTraySupported() {
 390         return false;
 391     }
 392 
 393     static native ColorModel makeColorModel();
 394     static ColorModel screenmodel;
 395 
 396     static ColorModel getStaticColorModel() {
 397         if (screenmodel == null) {
 398             screenmodel = config.getColorModel ();
 399         }
 400         return screenmodel;
 401     }
 402 
 403     public ColorModel getColorModel() {
 404         return getStaticColorModel();
 405     }
 406 
 407     public native int getScreenResolution();
 408 
 409     public Insets getScreenInsets(GraphicsConfiguration gc) {
 410         return new Insets(0,0,0,0);
 411     }
 412 
 413     protected native int getScreenWidth();
 414     protected native int getScreenHeight();
 415 
 416     public FontMetrics getFontMetrics(Font font) {
 417         /*
 418         // REMIND: platform font flag should be obsolete soon
 419         if (!RasterOutputManager.usesPlatformFont()) {
 420             return super.getFontMetrics(font);
 421         } else {
 422             return X11FontMetrics.getFontMetrics(font);
 423         }
 424         */
 425         return super.getFontMetrics(font);
 426     }
 427 
 428     public PrintJob getPrintJob(final Frame frame, final String doctitle,
 429                                 final Properties props) {
 430 
 431         if (GraphicsEnvironment.isHeadless()) {
 432             throw new IllegalArgumentException();
 433         }
 434 
 435         PrintJob2D printJob = new PrintJob2D(frame, doctitle, props);
 436 
 437         if (printJob.printDialog() == false) {
 438             printJob = null;
 439         }
 440 
 441         return printJob;
 442     }
 443 
 444     public PrintJob getPrintJob(final Frame frame, final String doctitle,
 445                                 final JobAttributes jobAttributes,
 446                                 final PageAttributes pageAttributes) {
 447 
 448 
 449         if (GraphicsEnvironment.isHeadless()) {
 450             throw new IllegalArgumentException();
 451         }
 452 
 453         PrintJob2D printJob = new PrintJob2D(frame, doctitle,
 454                                              jobAttributes, pageAttributes);
 455 
 456         if (printJob.printDialog() == false) {
 457             printJob = null;
 458         }
 459 
 460         return printJob;
 461     }
 462 
 463     public native void beep();
 464 
 465     public  Clipboard getSystemClipboard() {
 466         //SecurityManager security = System.getSecurityManager();
 467         //if (security != null) {
 468         //  security.checkSystemClipboardAccess();
 469         //}
 470         //synchronized (this) {
 471         //    if (clipboard == null) {
 472         //        clipboard = new X11Clipboard("System", "CLIPBOARD");
 473         //    }
 474         //}
 475         //return clipboard;
 476         return null;
 477     }
 478 
 479     public Clipboard getSystemSelection() {
 480         //SecurityManager security = System.getSecurityManager();
 481         //if (security != null) {
 482         //    security.checkSystemClipboardAccess();
 483         //}
 484         //synchronized (this) {
 485         //    if (selection == null) {
 486         //        selection = new X11Clipboard("Selection", "PRIMARY");
 487         //    }
 488         //}
 489         //return selection;
 490         return null;
 491     }
 492 
 493     public boolean getLockingKeyState(int key) {
 494         if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK ||
 495                key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) {
 496             throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState");
 497         }
 498         return getLockingKeyStateNative(key);
 499     }
 500 
 501     public native boolean getLockingKeyStateNative(int key);
 502 
 503     public native void loadSystemColors(int[] systemColors);
 504 
 505     /**
 506      * Give native peers the ability to query the native container
 507      * given a native component (e.g. the direct parent may be lightweight).
 508      */
 509     public static Container getNativeContainer(Component c) {
 510         return Toolkit.getNativeContainer(c);
 511     }
 512 
 513     protected static final Object targetToPeer(Object target) {
 514         return SunToolkit.targetToPeer(target);
 515     }
 516 
 517     protected static final void targetDisposedPeer(Object target, Object peer) {
 518         SunToolkit.targetDisposedPeer(target, peer);
 519     }
 520 
 521     public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {
 522         //if (MToolkit.useMotifDnD()) {
 523         //    return MDragSourceContextPeer.createDragSourceContextPeer(dge);
 524         //} else {
 525         //    return X11DragSourceContextPeer.createDragSourceContextPeer(dge);
 526         //}
 527         return null;
 528     }
 529 
 530     public <T extends DragGestureRecognizer> T
 531         createDragGestureRecognizer(Class<T> abstractRecognizerClass,
 532                                     DragSource ds, Component c, int srcActions,
 533                                     DragGestureListener dgl)
 534     {
 535         //if (MouseDragGestureRecognizer.class.equals(abstractRecognizerClass))
 536         //    return (T)new MMouseDragGestureRecognizer(ds, c, srcActions, dgl);
 537         //else
 538             return null;
 539     }
 540 
 541     /**
 542      * Returns a new input method adapter descriptor for native input methods.
 543      */
 544     public InputMethodDescriptor getInputMethodAdapterDescriptor() throws AWTException {
 545         return null; // return new MInputMethodDescriptor();
 546     }
 547 
 548     /**
 549      * Returns a style map for the input method highlight.
 550      */
 551     public Map mapInputMethodHighlight(InputMethodHighlight highlight) {
 552         return null; //return MInputMethod.mapInputMethodHighlight(highlight);
 553     }
 554 
 555     /**
 556      * Returns a new custom cursor.
 557      */
 558     public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
 559         throws IndexOutOfBoundsException {
 560         return null; //return new MCustomCursor(cursor, hotSpot, name);
 561     }
 562 
 563     /**
 564      * Returns the supported cursor size
 565      */
 566     public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) {
 567         return null; //MCustomCursor.getBestCursorSize(
 568             //java.lang.Math.max(1,preferredWidth), java.lang.Math.max(1,preferredHeight));
 569     }
 570 
 571     public int getMaximumCursorColors() {
 572         return 2;  // Black and white.
 573     }
 574 
 575     private final static String prefix  = "DnD.Cursor.";
 576     private final static String postfix = ".32x32";
 577     private static final String dndPrefix  = "DnD.";
 578 
 579     protected Object lazilyLoadDesktopProperty(String name) {
 580         if (name.startsWith(prefix)) {
 581             String cursorName = name.substring(prefix.length(), name.length()) + postfix;
 582 
 583             try {
 584                 return Cursor.getSystemCustomCursor(cursorName);
 585             } catch (AWTException awte) {
 586                 System.err.println("cannot load system cursor: " + cursorName);
 587 
 588                 return null;
 589             }
 590         }
 591 
 592         if (name.equals("awt.dynamicLayoutSupported")) {
 593             return lazilyLoadDynamicLayoutSupportedProperty(name);
 594         }
 595 
 596         if (!loadedXSettings &&
 597             (name.startsWith("gnome.") ||
 598              name.equals(SunToolkit.DESKTOPFONTHINTS) ||
 599              name.startsWith(dndPrefix))) {
 600             loadedXSettings = true;
 601             if (!GraphicsEnvironment.isHeadless()) {
 602                 loadXSettings();
 603                 desktopProperties.put(SunToolkit.DESKTOPFONTHINTS,
 604                                       SunToolkit.getDesktopFontHints());
 605                 return desktopProperties.get(name);
 606             }
 607         }
 608 
 609         return super.lazilyLoadDesktopProperty(name);
 610     }
 611 
 612     /*
 613      * Called from lazilyLoadDesktopProperty because we may not know if
 614      * the user has quit the previous window manager and started another.
 615      */
 616     protected Boolean lazilyLoadDynamicLayoutSupportedProperty(String name) {
 617         boolean nativeDynamic = isDynamicLayoutSupportedNative();
 618 
 619         if (log.isLoggable(Level.FINER)) {
 620             log.log(Level.FINER, "nativeDynamic == " + nativeDynamic);
 621         }
 622 
 623         return Boolean.valueOf(nativeDynamic);
 624     }
 625 
 626     private native int getMulticlickTime();
 627 
 628     protected void initializeDesktopProperties() {
 629         desktopProperties.put("DnD.Autoscroll.initialDelay",     Integer.valueOf(50));
 630         desktopProperties.put("DnD.Autoscroll.interval",         Integer.valueOf(50));
 631         desktopProperties.put("DnD.Autoscroll.cursorHysteresis", Integer.valueOf(5));
 632 
 633         /* As of 1.4, no wheel mice are supported on Solaris
 634          * however, they are on Linux, and there isn't a way to detect them,
 635          * so we leave this property unset to indicate we're not sure if there's
 636          * a wheel mouse or not.
 637          */
 638         //desktopProperties.put("awt.wheelMousePresent", Boolean.valueOf(false));
 639 
 640         // We don't want to call getMultilclickTime() if we're headless
 641         if (!GraphicsEnvironment.isHeadless()) {
 642             desktopProperties.put("awt.multiClickInterval",
 643                                   Integer.valueOf(getMulticlickTime()));
 644             desktopProperties.put("awt.mouse.numButtons",
 645                                   Integer.valueOf(getNumberOfButtons()));
 646         }
 647     }
 648 
 649     public RobotPeer createRobot(Robot target, GraphicsDevice screen) {
 650         /* 'target' is unused for now... */
 651         //return new MRobotPeer(screen.getDefaultConfiguration());
 652         return null;
 653     }
 654 
 655     static boolean useMotifDnD() {
 656         return motifdnd;
 657     }
 658 
 659     //
 660     // The following support Gnome's equivalent of desktop properties.
 661     // A writeup of this can be found at:
 662     // http://www.freedesktop.org/standards/xsettings/xsettings.html
 663     //
 664 
 665     /**
 666      * Triggers a callback to parseXSettings with the x settings values
 667      * from the window server. Note that this will NOT call
 668      * parseXSettings if we are not running on a GNOME desktop.
 669      */
 670     private native void loadXSettings();
 671 
 672     /**
 673      * Callback from the native side indicating some, or all, of the
 674      * desktop properties have changed and need to be reloaded.
 675      * <code>data</code> is the byte array directly from the x server and
 676      * may be in little endian format.
 677      * <p>
 678      * NB: This could be called from any thread if triggered by
 679      * <code>loadXSettings</code>.  It is called from the toolkit
 680      * thread if triggered by an XSETTINGS change.
 681      */
 682     private void parseXSettings(int screen_XXX_ignored, byte[] data) {
 683         // XXX: notyet: map screen -> per screen XSettings object
 684         // for now native code only calls us for default screen
 685         // see awt_MToolkit.c awt_xsettings_update().
 686         if (xs == null) {
 687             xs = new XSettings();
 688         }
 689 
 690         Map updatedSettings = xs.update(data);
 691         if (updatedSettings == null || updatedSettings.isEmpty()) {
 692             return;
 693         }
 694 
 695         Iterator i = updatedSettings.entrySet().iterator();
 696         while (i.hasNext()) {
 697             Map.Entry e = (Map.Entry)i.next();
 698             String name = (String)e.getKey();
 699 
 700             name = "gnome." + name;
 701             setDesktopProperty(name, e.getValue());
 702 
 703             // XXX: we probably want to do something smarter.  In
 704             // particular, "Net" properties are of interest to the
 705             // "core" AWT itself.  E.g.
 706             //
 707             // Net/DndDragThreshold -> ???
 708             // Net/DoubleClickTime  -> awt.multiClickInterval
 709         }
 710 
 711         setDesktopProperty(SunToolkit.DESKTOPFONTHINTS,
 712                            SunToolkit.getDesktopFontHints());
 713 
 714         Integer dragThreshold = null;
 715         synchronized (this) {
 716             dragThreshold = (Integer)desktopProperties.get("gnome.Net/DndDragThreshold");
 717         }
 718         if (dragThreshold != null) {
 719             setDesktopProperty("DnD.gestureMotionThreshold", dragThreshold);
 720         }
 721     }
 722 
 723     protected boolean needsXEmbedImpl() {
 724         return true;
 725     }
 726 
 727     public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
 728         return (modalityType == Dialog.ModalityType.MODELESS) ||
 729                (modalityType == Dialog.ModalityType.APPLICATION_MODAL);
 730     }
 731 
 732     public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
 733         return (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE);
 734     }
 735 
 736     private native boolean isSyncUpdated();
 737     private native boolean isSyncFailed();
 738     private native int getEventNumber();
 739     private native void updateSyncSelection();
 740     private static final long WORKAROUND_SLEEP = 100;
 741 
 742     /**
 743      * @inheritDoc
 744      */
 745     protected boolean syncNativeQueue(final long timeout) {
 746         awtLock();
 747         try {
 748             long event_number = getEventNumber();
 749             updateSyncSelection();
 750 
 751             // Wait for selection notify for oops on win
 752             long start = System.currentTimeMillis();
 753             while (!isSyncUpdated() && !isSyncFailed()) {
 754                 try {
 755                     awtLockWait(timeout);
 756                 } catch (InterruptedException e) {
 757                     throw new RuntimeException(e);
 758                 }
 759                 // This "while" is a protection from spurious
 760                 // wake-ups.  However, we shouldn't wait for too long
 761                 if (((System.currentTimeMillis() - start) > timeout) && (timeout >= 0)) {
 762                     throw new OperationTimedOut();
 763                 }
 764             }
 765             if (isSyncFailed() && getEventNumber() - event_number == 1) {
 766                 awtUnlock();
 767                 try {
 768                     Thread.sleep(WORKAROUND_SLEEP);
 769                 } catch (InterruptedException ie) {
 770                     throw new RuntimeException(ie);
 771                 } finally {
 772                     awtLock();
 773                 }
 774             }
 775             return getEventNumber() - event_number > 2;
 776         } finally {
 777             awtUnlock();
 778         }
 779     }
 780 
 781     public  void grab(Window w) {
 782         WindowPeer peer = (WindowPeer)w.getPeer();
 783         if (peer != null) {
 784             nativeGrab(peer);
 785         }
 786     }
 787 
 788     public void ungrab(Window w) {
 789         WindowPeer peer = (WindowPeer)w.getPeer();
 790         if (peer != null) {
 791             nativeUnGrab(peer);
 792         }
 793     }
 794     private native void nativeGrab(WindowPeer peer);
 795     private native void nativeUnGrab(WindowPeer peer);
 796 
 797 
 798     public boolean isDesktopSupported(){
 799         return false;
 800     }
 801 
 802     public DesktopPeer createDesktopPeer(Desktop target)
 803     throws HeadlessException{
 804         throw new UnsupportedOperationException();
 805     }
 806 
 807     public final static int
 808         UNDETERMINED_WM = 1,
 809         NO_WM = 2,
 810         OTHER_WM = 3,
 811         OPENLOOK_WM = 4,
 812         MOTIF_WM = 5,
 813         CDE_WM = 6,
 814         ENLIGHTEN_WM = 7,
 815         KDE2_WM = 8,
 816         SAWFISH_WM = 9,
 817         ICE_WM = 10,
 818         METACITY_WM = 11,
 819         COMPIZ_WM = 12,
 820         LG3D_WM = 13;
 821 
 822     public static int getWMID() {
 823         String wmName = getWMName();
 824 
 825         if ("NO_WM".equals(wmName)) {
 826             return NO_WM;
 827         } else if ("OTHER_WM".equals(wmName)) {
 828             return OTHER_WM;
 829         } else if ("ENLIGHTEN_WM".equals(wmName)) {
 830             return ENLIGHTEN_WM;
 831         } else if ("KDE2_WM".equals(wmName)) {
 832             return KDE2_WM;
 833         } else if ("SAWFISH_WM".equals(wmName)) {
 834             return SAWFISH_WM;
 835         } else if ("ICE_WM".equals(wmName)) {
 836             return ICE_WM;
 837         } else if ("METACITY_WM".equals(wmName)) {
 838             return METACITY_WM;
 839         } else if ("OPENLOOK_WM".equals(wmName)) {
 840             return OPENLOOK_WM;
 841         } else if ("MOTIF_WM".equals(wmName)) {
 842             return MOTIF_WM;
 843         } else if ("CDE_WM".equals(wmName)) {
 844             return CDE_WM;
 845         } else if ("COMPIZ_WM".equals(wmName)) {
 846             return COMPIZ_WM;
 847         } else if ("LG3D_WM".equals(wmName)) {
 848             return LG3D_WM;
 849         }
 850         return UNDETERMINED_WM;
 851     }
 852 
 853     private static native String getWMName();
 854 
 855 } // class MToolkit