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 MenuBarPeer createMenuBar(MenuBar target) {
 306         //MenuBarPeer peer = new MMenuBarPeer(target);
 307         //targetCreatedPeer(target, peer);
 308         //return peer;
 309         return null;
 310     }
 311 
 312     public MenuPeer createMenu(Menu target) {
 313         //MenuPeer peer = new MMenuPeer(target);
 314         //targetCreatedPeer(target, peer);
 315         //return peer;
 316         return null;
 317     }
 318 
 319     public PopupMenuPeer createPopupMenu(PopupMenu target) {
 320         //PopupMenuPeer peer = new MPopupMenuPeer(target);
 321         //targetCreatedPeer(target, peer);
 322         //return peer;
 323         return null;
 324     }
 325 
 326     public MenuItemPeer createMenuItem(MenuItem target) {
 327         //MenuItemPeer peer = new MMenuItemPeer(target);
 328         //targetCreatedPeer(target, peer);
 329         //return peer;
 330         return null;
 331     }
 332 
 333     public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) {
 334         //CheckboxMenuItemPeer peer = new MCheckboxMenuItemPeer(target);
 335         //targetCreatedPeer(target, peer);
 336         //return peer;
 337         return null;
 338     }
 339 
 340     public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) {
 341         return null;
 342     }
 343 
 344     //public MEmbeddedFramePeer createEmbeddedFrame(MEmbeddedFrame target)
 345     //{
 346         //MEmbeddedFramePeer peer = new MEmbeddedFramePeer(target);
 347         //targetCreatedPeer(target, peer);
 348         //return peer;
 349     //    return null;
 350     //}
 351 
 352 
 353     public FontPeer getFontPeer(String name, int style){
 354         return new MFontPeer(name, style);
 355     }
 356 
 357     /*
 358      * On X, support for dynamic layout on resizing is governed by the
 359      * window manager.  If the window manager supports it, it happens
 360      * automatically.  The setter method for this property is
 361      * irrelevant on X.
 362      */
 363     public void setDynamicLayout(boolean b) {
 364         dynamicLayoutSetting = b;
 365     }
 366 
 367     protected boolean isDynamicLayoutSet() {
 368         return dynamicLayoutSetting;
 369     }
 370 
 371     /* Called from isDynamicLayoutActive() and from
 372      * lazilyLoadDynamicLayoutSupportedProperty()
 373      */
 374     protected native boolean isDynamicLayoutSupportedNative();
 375 
 376     public boolean isDynamicLayoutActive() {
 377         return isDynamicLayoutSupportedNative();
 378     }
 379 
 380     public native boolean isFrameStateSupported(int state);
 381 
 382     public TrayIconPeer createTrayIcon(TrayIcon target) throws HeadlessException {
 383         return null;
 384     }
 385 
 386     public SystemTrayPeer createSystemTray(SystemTray target) throws HeadlessException {
 387         return null;
 388     }
 389 
 390     public boolean isTraySupported() {
 391         return false;
 392     }
 393 
 394     static native ColorModel makeColorModel();
 395     static ColorModel screenmodel;
 396 
 397     static ColorModel getStaticColorModel() {
 398         if (screenmodel == null) {
 399             screenmodel = config.getColorModel ();
 400         }
 401         return screenmodel;
 402     }
 403 
 404     public ColorModel getColorModel() {
 405         return getStaticColorModel();
 406     }
 407 
 408     public native int getScreenResolution();
 409 
 410     public Insets getScreenInsets(GraphicsConfiguration gc) {
 411         return new Insets(0,0,0,0);
 412     }
 413 
 414     protected native int getScreenWidth();
 415     protected native int getScreenHeight();
 416 
 417     public FontMetrics getFontMetrics(Font font) {
 418         /*
 419         // REMIND: platform font flag should be obsolete soon
 420         if (!RasterOutputManager.usesPlatformFont()) {
 421             return super.getFontMetrics(font);
 422         } else {
 423             return X11FontMetrics.getFontMetrics(font);
 424         }
 425         */
 426         return super.getFontMetrics(font);
 427     }
 428 
 429     public PrintJob getPrintJob(final Frame frame, final String doctitle,
 430                                 final Properties props) {
 431 
 432         if (GraphicsEnvironment.isHeadless()) {
 433             throw new IllegalArgumentException();
 434         }
 435 
 436         PrintJob2D printJob = new PrintJob2D(frame, doctitle, props);
 437 
 438         if (printJob.printDialog() == false) {
 439             printJob = null;
 440         }
 441 
 442         return printJob;
 443     }
 444 
 445     public PrintJob getPrintJob(final Frame frame, final String doctitle,
 446                                 final JobAttributes jobAttributes,
 447                                 final PageAttributes pageAttributes) {
 448 
 449 
 450         if (GraphicsEnvironment.isHeadless()) {
 451             throw new IllegalArgumentException();
 452         }
 453 
 454         PrintJob2D printJob = new PrintJob2D(frame, doctitle,
 455                                              jobAttributes, pageAttributes);
 456 
 457         if (printJob.printDialog() == false) {
 458             printJob = null;
 459         }
 460 
 461         return printJob;
 462     }
 463 
 464     public native void beep();
 465 
 466     public  Clipboard getSystemClipboard() {
 467         //SecurityManager security = System.getSecurityManager();
 468         //if (security != null) {
 469         //  security.checkSystemClipboardAccess();
 470         //}
 471         //synchronized (this) {
 472         //    if (clipboard == null) {
 473         //        clipboard = new X11Clipboard("System", "CLIPBOARD");
 474         //    }
 475         //}
 476         //return clipboard;
 477         return null;
 478     }
 479 
 480     public Clipboard getSystemSelection() {
 481         //SecurityManager security = System.getSecurityManager();
 482         //if (security != null) {
 483         //    security.checkSystemClipboardAccess();
 484         //}
 485         //synchronized (this) {
 486         //    if (selection == null) {
 487         //        selection = new X11Clipboard("Selection", "PRIMARY");
 488         //    }
 489         //}
 490         //return selection;
 491         return null;
 492     }
 493 
 494     public boolean getLockingKeyState(int key) {
 495         if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK ||
 496                key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) {
 497             throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState");
 498         }
 499         return getLockingKeyStateNative(key);
 500     }
 501 
 502     public native boolean getLockingKeyStateNative(int key);
 503 
 504     public native void loadSystemColors(int[] systemColors);
 505 
 506     /**
 507      * Give native peers the ability to query the native container
 508      * given a native component (e.g. the direct parent may be lightweight).
 509      */
 510     public static Container getNativeContainer(Component c) {
 511         return Toolkit.getNativeContainer(c);
 512     }
 513 
 514     protected static final Object targetToPeer(Object target) {
 515         return SunToolkit.targetToPeer(target);
 516     }
 517 
 518     protected static final void targetDisposedPeer(Object target, Object peer) {
 519         SunToolkit.targetDisposedPeer(target, peer);
 520     }
 521 
 522     public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {
 523         //if (MToolkit.useMotifDnD()) {
 524         //    return MDragSourceContextPeer.createDragSourceContextPeer(dge);
 525         //} else {
 526         //    return X11DragSourceContextPeer.createDragSourceContextPeer(dge);
 527         //}
 528         return null;
 529     }
 530 
 531     public <T extends DragGestureRecognizer> T
 532         createDragGestureRecognizer(Class<T> abstractRecognizerClass,
 533                                     DragSource ds, Component c, int srcActions,
 534                                     DragGestureListener dgl)
 535     {
 536         //if (MouseDragGestureRecognizer.class.equals(abstractRecognizerClass))
 537         //    return (T)new MMouseDragGestureRecognizer(ds, c, srcActions, dgl);
 538         //else
 539             return null;
 540     }
 541 
 542     /**
 543      * Returns a new input method adapter descriptor for native input methods.
 544      */
 545     public InputMethodDescriptor getInputMethodAdapterDescriptor() throws AWTException {
 546         return null; // return new MInputMethodDescriptor();
 547     }
 548 
 549     /**
 550      * Returns a style map for the input method highlight.
 551      */
 552     public Map mapInputMethodHighlight(InputMethodHighlight highlight) {
 553         return null; //return MInputMethod.mapInputMethodHighlight(highlight);
 554     }
 555 
 556     /**
 557      * Returns a new custom cursor.
 558      */
 559     public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
 560         throws IndexOutOfBoundsException {
 561         return null; //return new MCustomCursor(cursor, hotSpot, name);
 562     }
 563 
 564     /**
 565      * Returns the supported cursor size
 566      */
 567     public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) {
 568         return null; //MCustomCursor.getBestCursorSize(
 569             //java.lang.Math.max(1,preferredWidth), java.lang.Math.max(1,preferredHeight));
 570     }
 571 
 572     public int getMaximumCursorColors() {
 573         return 2;  // Black and white.
 574     }
 575 
 576     private final static String prefix  = "DnD.Cursor.";
 577     private final static String postfix = ".32x32";
 578     private static final String dndPrefix  = "DnD.";
 579 
 580     protected Object lazilyLoadDesktopProperty(String name) {
 581         if (name.startsWith(prefix)) {
 582             String cursorName = name.substring(prefix.length(), name.length()) + postfix;
 583 
 584             try {
 585                 return Cursor.getSystemCustomCursor(cursorName);
 586             } catch (AWTException awte) {
 587                 System.err.println("cannot load system cursor: " + cursorName);
 588 
 589                 return null;
 590             }
 591         }
 592 
 593         if (name.equals("awt.dynamicLayoutSupported")) {
 594             return lazilyLoadDynamicLayoutSupportedProperty(name);
 595         }
 596 
 597         if (!loadedXSettings &&
 598             (name.startsWith("gnome.") ||
 599              name.equals(SunToolkit.DESKTOPFONTHINTS) ||
 600              name.startsWith(dndPrefix))) {
 601             loadedXSettings = true;
 602             if (!GraphicsEnvironment.isHeadless()) {
 603                 loadXSettings();
 604                 desktopProperties.put(SunToolkit.DESKTOPFONTHINTS,
 605                                       SunToolkit.getDesktopFontHints());
 606                 return desktopProperties.get(name);
 607             }
 608         }
 609 
 610         return super.lazilyLoadDesktopProperty(name);
 611     }
 612 
 613     /*
 614      * Called from lazilyLoadDesktopProperty because we may not know if
 615      * the user has quit the previous window manager and started another.
 616      */
 617     protected Boolean lazilyLoadDynamicLayoutSupportedProperty(String name) {
 618         boolean nativeDynamic = isDynamicLayoutSupportedNative();
 619 
 620         if (log.isLoggable(PlatformLogger.FINER)) {
 621             log.finer("nativeDynamic == " + nativeDynamic);
 622         }
 623 
 624         return Boolean.valueOf(nativeDynamic);
 625     }
 626 
 627     private native int getMulticlickTime();
 628 
 629     protected void initializeDesktopProperties() {
 630         desktopProperties.put("DnD.Autoscroll.initialDelay",     Integer.valueOf(50));
 631         desktopProperties.put("DnD.Autoscroll.interval",         Integer.valueOf(50));
 632         desktopProperties.put("DnD.Autoscroll.cursorHysteresis", Integer.valueOf(5));
 633 
 634         /* As of 1.4, no wheel mice are supported on Solaris
 635          * however, they are on Linux, and there isn't a way to detect them,
 636          * so we leave this property unset to indicate we're not sure if there's
 637          * a wheel mouse or not.
 638          */
 639         //desktopProperties.put("awt.wheelMousePresent", Boolean.valueOf(false));
 640 
 641         // We don't want to call getMultilclickTime() if we're headless
 642         if (!GraphicsEnvironment.isHeadless()) {
 643             desktopProperties.put("awt.multiClickInterval",
 644                                   Integer.valueOf(getMulticlickTime()));
 645             desktopProperties.put("awt.mouse.numButtons",
 646                                   Integer.valueOf(getNumberOfButtons()));
 647         }
 648     }
 649 
 650     public RobotPeer createRobot(Robot target, GraphicsDevice screen) {
 651         /* 'target' is unused for now... */
 652         //return new MRobotPeer(screen.getDefaultConfiguration());
 653         return null;
 654     }
 655 
 656     static boolean useMotifDnD() {
 657         return motifdnd;
 658     }
 659 
 660     //
 661     // The following support Gnome's equivalent of desktop properties.
 662     // A writeup of this can be found at:
 663     // http://www.freedesktop.org/standards/xsettings/xsettings.html
 664     //
 665 
 666     /**
 667      * Triggers a callback to parseXSettings with the x settings values
 668      * from the window server. Note that this will NOT call
 669      * parseXSettings if we are not running on a GNOME desktop.
 670      */
 671     private native void loadXSettings();
 672 
 673     /**
 674      * Callback from the native side indicating some, or all, of the
 675      * desktop properties have changed and need to be reloaded.
 676      * <code>data</code> is the byte array directly from the x server and
 677      * may be in little endian format.
 678      * <p>
 679      * NB: This could be called from any thread if triggered by
 680      * <code>loadXSettings</code>.  It is called from the toolkit
 681      * thread if triggered by an XSETTINGS change.
 682      */
 683     private void parseXSettings(int screen_XXX_ignored, byte[] data) {
 684         // XXX: notyet: map screen -> per screen XSettings object
 685         // for now native code only calls us for default screen
 686         // see awt_MToolkit.c awt_xsettings_update().
 687         if (xs == null) {
 688             xs = new XSettings();
 689         }
 690 
 691         Map updatedSettings = xs.update(data);
 692         if (updatedSettings == null || updatedSettings.isEmpty()) {
 693             return;
 694         }
 695 
 696         Iterator i = updatedSettings.entrySet().iterator();
 697         while (i.hasNext()) {
 698             Map.Entry e = (Map.Entry)i.next();
 699             String name = (String)e.getKey();
 700 
 701             name = "gnome." + name;
 702             setDesktopProperty(name, e.getValue());
 703 
 704             // XXX: we probably want to do something smarter.  In
 705             // particular, "Net" properties are of interest to the
 706             // "core" AWT itself.  E.g.
 707             //
 708             // Net/DndDragThreshold -> ???
 709             // Net/DoubleClickTime  -> awt.multiClickInterval
 710         }
 711 
 712         setDesktopProperty(SunToolkit.DESKTOPFONTHINTS,
 713                            SunToolkit.getDesktopFontHints());
 714 
 715         Integer dragThreshold = null;
 716         synchronized (this) {
 717             dragThreshold = (Integer)desktopProperties.get("gnome.Net/DndDragThreshold");
 718         }
 719         if (dragThreshold != null) {
 720             setDesktopProperty("DnD.gestureMotionThreshold", dragThreshold);
 721         }
 722     }
 723 
 724     protected boolean needsXEmbedImpl() {
 725         return true;
 726     }
 727 
 728     public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
 729         return (modalityType == Dialog.ModalityType.MODELESS) ||
 730                (modalityType == Dialog.ModalityType.APPLICATION_MODAL);
 731     }
 732 
 733     public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
 734         return (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE);
 735     }
 736 
 737     private native boolean isSyncUpdated();
 738     private native boolean isSyncFailed();
 739     private native int getEventNumber();
 740     private native void updateSyncSelection();
 741     private static final long WORKAROUND_SLEEP = 100;
 742 
 743     /**
 744      * @inheritDoc
 745      */
 746     protected boolean syncNativeQueue(final long timeout) {
 747         awtLock();
 748         try {
 749             long event_number = getEventNumber();
 750             updateSyncSelection();
 751 
 752             // Wait for selection notify for oops on win
 753             long start = System.currentTimeMillis();
 754             while (!isSyncUpdated() && !isSyncFailed()) {
 755                 try {
 756                     awtLockWait(timeout);
 757                 } catch (InterruptedException e) {
 758                     throw new RuntimeException(e);
 759                 }
 760                 // This "while" is a protection from spurious
 761                 // wake-ups.  However, we shouldn't wait for too long
 762                 if (((System.currentTimeMillis() - start) > timeout) && (timeout >= 0)) {
 763                     throw new OperationTimedOut();
 764                 }
 765             }
 766             if (isSyncFailed() && getEventNumber() - event_number == 1) {
 767                 awtUnlock();
 768                 try {
 769                     Thread.sleep(WORKAROUND_SLEEP);
 770                 } catch (InterruptedException ie) {
 771                     throw new RuntimeException(ie);
 772                 } finally {
 773                     awtLock();
 774                 }
 775             }
 776             return getEventNumber() - event_number > 2;
 777         } finally {
 778             awtUnlock();
 779         }
 780     }
 781 
 782     public  void grab(Window w) {
 783         WindowPeer peer = (WindowPeer)w.getPeer();
 784         if (peer != null) {
 785             nativeGrab(peer);
 786         }
 787     }
 788 
 789     public void ungrab(Window w) {
 790         WindowPeer peer = (WindowPeer)w.getPeer();
 791         if (peer != null) {
 792             nativeUnGrab(peer);
 793         }
 794     }
 795     private native void nativeGrab(WindowPeer peer);
 796     private native void nativeUnGrab(WindowPeer peer);
 797 
 798 
 799     public boolean isDesktopSupported(){
 800         return false;
 801     }
 802 
 803     public DesktopPeer createDesktopPeer(Desktop target)
 804     throws HeadlessException{
 805         throw new UnsupportedOperationException();
 806     }
 807 
 808     public final static int
 809         UNDETERMINED_WM = 1,
 810         NO_WM = 2,
 811         OTHER_WM = 3,
 812         OPENLOOK_WM = 4,
 813         MOTIF_WM = 5,
 814         CDE_WM = 6,
 815         ENLIGHTEN_WM = 7,
 816         KDE2_WM = 8,
 817         SAWFISH_WM = 9,
 818         ICE_WM = 10,
 819         METACITY_WM = 11,
 820         COMPIZ_WM = 12,
 821         LG3D_WM = 13;
 822 
 823     public static int getWMID() {
 824         String wmName = getWMName();
 825 
 826         if ("NO_WM".equals(wmName)) {
 827             return NO_WM;
 828         } else if ("OTHER_WM".equals(wmName)) {
 829             return OTHER_WM;
 830         } else if ("ENLIGHTEN_WM".equals(wmName)) {
 831             return ENLIGHTEN_WM;
 832         } else if ("KDE2_WM".equals(wmName)) {
 833             return KDE2_WM;
 834         } else if ("SAWFISH_WM".equals(wmName)) {
 835             return SAWFISH_WM;
 836         } else if ("ICE_WM".equals(wmName)) {
 837             return ICE_WM;
 838         } else if ("METACITY_WM".equals(wmName)) {
 839             return METACITY_WM;
 840         } else if ("OPENLOOK_WM".equals(wmName)) {
 841             return OPENLOOK_WM;
 842         } else if ("MOTIF_WM".equals(wmName)) {
 843             return MOTIF_WM;
 844         } else if ("CDE_WM".equals(wmName)) {
 845             return CDE_WM;
 846         } else if ("COMPIZ_WM".equals(wmName)) {
 847             return COMPIZ_WM;
 848         } else if ("LG3D_WM".equals(wmName)) {
 849             return LG3D_WM;
 850         }
 851         return UNDETERMINED_WM;
 852     }
 853 
 854     private static native String getWMName();
 855 
 856 } // class MToolkit