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