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