1 /*
   2  * Copyright (c) 1996, 2014, 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.windows;
  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.event.KeyEvent;
  34 import java.awt.datatransfer.Clipboard;
  35 import java.awt.TrayIcon;
  36 import java.beans.PropertyChangeListener;
  37 import java.security.AccessController;
  38 import java.security.PrivilegedAction;
  39 import sun.awt.AWTAutoShutdown;
  40 import sun.awt.AppContext;
  41 import sun.awt.SunToolkit;
  42 import sun.misc.ThreadGroupUtils;
  43 import sun.awt.Win32GraphicsDevice;
  44 import sun.awt.Win32GraphicsEnvironment;
  45 import sun.java2d.d3d.D3DRenderQueue;
  46 import sun.java2d.opengl.OGLRenderQueue;
  47 
  48 import sun.print.PrintJob2D;
  49 
  50 import java.awt.dnd.DragSource;
  51 import java.awt.dnd.DragGestureListener;
  52 import java.awt.dnd.DragGestureEvent;
  53 import java.awt.dnd.DragGestureRecognizer;
  54 import java.awt.dnd.MouseDragGestureRecognizer;
  55 import java.awt.dnd.InvalidDnDOperationException;
  56 import java.awt.dnd.peer.DragSourceContextPeer;
  57 
  58 import java.util.Hashtable;
  59 import java.util.Locale;
  60 import java.util.Map;
  61 import java.util.Properties;
  62 
  63 import sun.font.FontManager;
  64 import sun.font.FontManagerFactory;
  65 import sun.font.SunFontManager;
  66 import sun.misc.PerformanceLogger;
  67 import sun.util.logging.PlatformLogger;
  68 
  69 public class WToolkit extends SunToolkit implements Runnable {
  70 
  71     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WToolkit");
  72 
  73     static GraphicsConfiguration config;
  74 
  75     // System clipboard.
  76     WClipboard clipboard;
  77 
  78     // cache of font peers
  79     private Hashtable cacheFontPeer;
  80 
  81     // Windows properties
  82     private WDesktopProperties  wprops;
  83 
  84     // Dynamic Layout Resize client code setting
  85     protected boolean dynamicLayoutSetting = false;
  86 
  87     //Is it allowed to generate events assigned to extra mouse buttons.
  88     //Set to true by default.
  89     private static boolean areExtraMouseButtonsEnabled = true;
  90 
  91     /**
  92      * Initialize JNI field and method IDs
  93      */
  94     private static native void initIDs();
  95     private static boolean loaded = false;
  96     public static void loadLibraries() {
  97         if (!loaded) {
  98             java.security.AccessController.doPrivileged(
  99                           new sun.security.action.LoadLibraryAction("awt"));
 100             loaded = true;
 101         }
 102     }
 103 
 104     private static native String getWindowsVersion();
 105 
 106     static {
 107         loadLibraries();
 108         initIDs();
 109 
 110         // Print out which version of Windows is running
 111         if (log.isLoggable(PlatformLogger.FINE)) {
 112             log.fine("Win version: " + getWindowsVersion());
 113         }
 114 
 115         java.security.AccessController.doPrivileged(
 116             new java.security.PrivilegedAction()
 117         {
 118             public Object run() {
 119                 String browserProp = System.getProperty("browser");
 120                 if (browserProp != null && browserProp.equals("sun.plugin")) {
 121                     disableCustomPalette();
 122                 }
 123                 return null;
 124             }
 125         });
 126     }
 127 
 128     private static native void disableCustomPalette();
 129 
 130     /*
 131      * Reset the static GraphicsConfiguration to the default.  Called on
 132      * startup and when display settings have changed.
 133      */
 134     public static void resetGC() {
 135         if (GraphicsEnvironment.isHeadless()) {
 136             config = null;
 137         } else {
 138           config = (GraphicsEnvironment
 139                   .getLocalGraphicsEnvironment()
 140           .getDefaultScreenDevice()
 141           .getDefaultConfiguration());
 142         }
 143     }
 144 
 145     /*
 146      * NOTE: The following embedded*() methods are non-public API intended
 147      * for internal use only.  The methods are unsupported and could go
 148      * away in future releases.
 149      *
 150      * New hook functions for using the AWT as an embedded service. These
 151      * functions replace the global C function AwtInit() which was previously
 152      * exported by awt.dll.
 153      *
 154      * When used as an embedded service, the AWT does NOT have its own
 155      * message pump. It instead relies on the parent application to provide
 156      * this functionality. embeddedInit() assumes that the thread on which it
 157      * is called is the message pumping thread. Violating this assumption
 158      * will lead to undefined behavior.
 159      *
 160      * embeddedInit must be called before the WToolkit() constructor.
 161      * embeddedDispose should be called before the applicaton terminates the
 162      * Java VM. It is currently unsafe to reinitialize the toolkit again
 163      * after it has been disposed. Instead, awt.dll must be reloaded and the
 164      * class loader which loaded WToolkit must be finalized before it is
 165      * safe to reuse AWT. Dynamic reusability may be added to the toolkit in
 166      * the future.
 167      */
 168 
 169     /**
 170      * Initializes the Toolkit for use in an embedded environment.
 171      *
 172      * @return true if the the initialization succeeded; false if it failed.
 173      *         The function will fail if the Toolkit was already initialized.
 174      * @since 1.3
 175      */
 176     public static native boolean embeddedInit();
 177 
 178     /**
 179      * Disposes the Toolkit in an embedded environment. This method should
 180      * not be called on exit unless the Toolkit was constructed with
 181      * embeddedInit.
 182      *
 183      * @return true if the disposal succeeded; false if it failed. The
 184      *         function will fail if the calling thread is not the same
 185      *         thread which called embeddedInit(), or if the Toolkit was
 186      *         already disposed.
 187      * @since 1.3
 188      */
 189     public static native boolean embeddedDispose();
 190 
 191     /**
 192      * To be called after processing the event queue by users of the above
 193      * embeddedInit() function.  The reason for this additional call is that
 194      * there are some operations performed during idle time in the AwtToolkit
 195      * event loop which should also be performed during idle time in any
 196      * other native event loop.  Failure to do so could result in
 197      * deadlocks.
 198      *
 199      * This method was added at the last minute of the jdk1.4 release
 200      * to work around a specific customer problem.  As with the above
 201      * embedded*() class, this method is non-public and should not be
 202      * used by external applications.
 203      *
 204      * See bug #4526587 for more information.
 205      */
 206     public native void embeddedEventLoopIdleProcessing();
 207 
 208     public static final String DATA_TRANSFERER_CLASS_NAME = "sun.awt.windows.WDataTransferer";
 209 
 210     static class ToolkitDisposer implements sun.java2d.DisposerRecord {
 211         public void dispose() {
 212             WToolkit.postDispose();
 213         }
 214     }
 215 
 216     private final Object anchor = new Object();
 217 
 218     private static native void postDispose();
 219 
 220     private static native boolean startToolkitThread(Runnable thread, ThreadGroup rootThreadGroup);
 221 
 222     public WToolkit() {
 223         // Startup toolkit threads
 224         if (PerformanceLogger.loggingEnabled()) {
 225             PerformanceLogger.setTime("WToolkit construction");
 226         }
 227 
 228         sun.java2d.Disposer.addRecord(anchor, new ToolkitDisposer());
 229 
 230         /*
 231          * Fix for 4701990.
 232          * AWTAutoShutdown state must be changed before the toolkit thread
 233          * starts to avoid race condition.
 234          */
 235         AWTAutoShutdown.notifyToolkitThreadBusy();
 236 
 237         // Find a root TG and attach Appkit thread to it
 238         ThreadGroup rootTG = AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
 239                     @Override
 240                     public ThreadGroup run() {
 241                         return ThreadGroupUtils.getRootThreadGroup();
 242                     }
 243                 });
 244         if (!startToolkitThread(this, rootTG)) {
 245             Thread toolkitThread = new Thread(rootTG, this, "AWT-Windows");
 246             toolkitThread.setDaemon(true);
 247             toolkitThread.start();
 248         }
 249 
 250         try {
 251             synchronized(this) {
 252                 while(!inited) {
 253                     wait();
 254                 }
 255             }
 256         } catch (InterruptedException x) {
 257             // swallow the exception
 258         }
 259 
 260         SunToolkit.setDataTransfererClassName(DATA_TRANSFERER_CLASS_NAME);
 261 
 262         // Enabled "live resizing" by default.  It remains controlled
 263         // by the native system though.
 264         setDynamicLayout(true);
 265 
 266         areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons", "true"));
 267         //set system property if not yet assigned
 268         System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled);
 269         setExtraMouseButtonsEnabledNative(areExtraMouseButtonsEnabled);
 270     }
 271 
 272     private final void registerShutdownHook() {
 273         AccessController.doPrivileged(new PrivilegedAction() {
 274             public Object run() {
 275                 Thread shutdown = new Thread(ThreadGroupUtils.getRootThreadGroup(), new Runnable() {
 276                     public void run() {
 277                         shutdown();
 278                     }
 279                 });
 280                 shutdown.setContextClassLoader(null);
 281                 Runtime.getRuntime().addShutdownHook(shutdown);
 282                 return null;
 283             }
 284         });
 285      }
 286 
 287     public void run() {
 288         AccessController.doPrivileged(new PrivilegedAction<Void>() {
 289             @Override
 290             public Void run() {
 291                 Thread.currentThread().setContextClassLoader(null);
 292                 return null;
 293             }
 294         });
 295         Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1);
 296         boolean startPump = init();
 297 
 298         if (startPump) {
 299             registerShutdownHook();
 300         }
 301 
 302         synchronized(this) {
 303             inited = true;
 304             notifyAll();
 305         }
 306 
 307         if (startPump) {
 308             eventLoop(); // will Dispose Toolkit when shutdown hook executes
 309         }
 310     }
 311 
 312     /*
 313      * eventLoop() begins the native message pump which retrieves and processes
 314      * native events.
 315      *
 316      * When shutdown() is called by the ShutdownHook added in run(), a
 317      * WM_QUIT message is posted to the Toolkit thread indicating that
 318      * eventLoop() should Dispose the toolkit and exit.
 319      */
 320     private native boolean init();
 321     private boolean inited = false;
 322 
 323     private native void eventLoop();
 324     private native void shutdown();
 325 
 326     /*
 327      * Instead of blocking the "AWT-Windows" thread uselessly on a semaphore,
 328      * use these functions. startSecondaryEventLoop() corresponds to wait()
 329      * and quitSecondaryEventLoop() corresponds to notify.
 330      *
 331      * These functions simulate blocking while allowing the AWT to continue
 332      * processing native events, eliminating a potential deadlock situation
 333      * with SendMessage.
 334      *
 335      * WARNING: startSecondaryEventLoop must only be called from the "AWT-
 336      * Windows" thread.
 337      */
 338     public static native void startSecondaryEventLoop();
 339     public static native void quitSecondaryEventLoop();
 340 
 341     /*
 342      * Create peer objects.
 343      */
 344 
 345     public ButtonPeer createButton(Button target) {
 346         ButtonPeer peer = new WButtonPeer(target);
 347         targetCreatedPeer(target, peer);
 348         return peer;
 349     }
 350 
 351     public TextFieldPeer createTextField(TextField target) {
 352         TextFieldPeer peer = new WTextFieldPeer(target);
 353         targetCreatedPeer(target, peer);
 354         return peer;
 355     }
 356 
 357     public LabelPeer createLabel(Label target) {
 358         LabelPeer peer = new WLabelPeer(target);
 359         targetCreatedPeer(target, peer);
 360         return peer;
 361     }
 362 
 363     public ListPeer createList(List target) {
 364         ListPeer peer = new WListPeer(target);
 365         targetCreatedPeer(target, peer);
 366         return peer;
 367     }
 368 
 369     public CheckboxPeer createCheckbox(Checkbox target) {
 370         CheckboxPeer peer = new WCheckboxPeer(target);
 371         targetCreatedPeer(target, peer);
 372         return peer;
 373     }
 374 
 375     public ScrollbarPeer createScrollbar(Scrollbar target) {
 376         ScrollbarPeer peer = new WScrollbarPeer(target);
 377         targetCreatedPeer(target, peer);
 378         return peer;
 379     }
 380 
 381     public ScrollPanePeer createScrollPane(ScrollPane target) {
 382         ScrollPanePeer peer = new WScrollPanePeer(target);
 383         targetCreatedPeer(target, peer);
 384         return peer;
 385     }
 386 
 387     public TextAreaPeer createTextArea(TextArea target) {
 388         TextAreaPeer peer = new WTextAreaPeer(target);
 389         targetCreatedPeer(target, peer);
 390         return peer;
 391     }
 392 
 393     public ChoicePeer createChoice(Choice target) {
 394         ChoicePeer peer = new WChoicePeer(target);
 395         targetCreatedPeer(target, peer);
 396         return peer;
 397     }
 398 
 399     public FramePeer  createFrame(Frame target) {
 400         FramePeer peer = new WFramePeer(target);
 401         targetCreatedPeer(target, peer);
 402         return peer;
 403     }
 404 
 405     public CanvasPeer createCanvas(Canvas target) {
 406         CanvasPeer peer = new WCanvasPeer(target);
 407         targetCreatedPeer(target, peer);
 408         return peer;
 409     }
 410 
 411     public void disableBackgroundErase(Canvas canvas) {
 412         WCanvasPeer peer = (WCanvasPeer)canvas.getPeer();
 413         if (peer == null) {
 414             throw new IllegalStateException("Canvas must have a valid peer");
 415         }
 416         peer.disableBackgroundErase();
 417     }
 418 
 419     public PanelPeer createPanel(Panel target) {
 420         PanelPeer peer = new WPanelPeer(target);
 421         targetCreatedPeer(target, peer);
 422         return peer;
 423     }
 424 
 425     public WindowPeer createWindow(Window target) {
 426         WindowPeer peer = new WWindowPeer(target);
 427         targetCreatedPeer(target, peer);
 428         return peer;
 429     }
 430 
 431     public DialogPeer createDialog(Dialog target) {
 432         DialogPeer peer = new WDialogPeer(target);
 433         targetCreatedPeer(target, peer);
 434         return peer;
 435     }
 436 
 437     public FileDialogPeer createFileDialog(FileDialog target) {
 438         FileDialogPeer peer = new WFileDialogPeer(target);
 439         targetCreatedPeer(target, peer);
 440         return peer;
 441     }
 442 
 443     public MenuBarPeer createMenuBar(MenuBar target) {
 444         MenuBarPeer peer = new WMenuBarPeer(target);
 445         targetCreatedPeer(target, peer);
 446         return peer;
 447     }
 448 
 449     public MenuPeer createMenu(Menu target) {
 450         MenuPeer peer = new WMenuPeer(target);
 451         targetCreatedPeer(target, peer);
 452         return peer;
 453     }
 454 
 455     public PopupMenuPeer createPopupMenu(PopupMenu target) {
 456         PopupMenuPeer peer = new WPopupMenuPeer(target);
 457         targetCreatedPeer(target, peer);
 458         return peer;
 459     }
 460 
 461     public MenuItemPeer createMenuItem(MenuItem target) {
 462         MenuItemPeer peer = new WMenuItemPeer(target);
 463         targetCreatedPeer(target, peer);
 464         return peer;
 465     }
 466 
 467     public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) {
 468         CheckboxMenuItemPeer peer = new WCheckboxMenuItemPeer(target);
 469         targetCreatedPeer(target, peer);
 470         return peer;
 471     }
 472 
 473     public RobotPeer createRobot(Robot target, GraphicsDevice screen) {
 474         // (target is unused for now)
 475         // Robot's don't need to go in the peer map since
 476         // they're not Component's
 477         return new WRobotPeer(screen);
 478     }
 479 
 480     public WEmbeddedFramePeer createEmbeddedFrame(WEmbeddedFrame target) {
 481         WEmbeddedFramePeer peer = new WEmbeddedFramePeer(target);
 482         targetCreatedPeer(target, peer);
 483         return peer;
 484     }
 485 
 486     WPrintDialogPeer createWPrintDialog(WPrintDialog target) {
 487         WPrintDialogPeer peer = new WPrintDialogPeer(target);
 488         targetCreatedPeer(target, peer);
 489         return peer;
 490     }
 491 
 492     WPageDialogPeer createWPageDialog(WPageDialog target) {
 493         WPageDialogPeer peer = new WPageDialogPeer(target);
 494         targetCreatedPeer(target, peer);
 495         return peer;
 496     }
 497 
 498     public TrayIconPeer createTrayIcon(TrayIcon target) {
 499         WTrayIconPeer peer = new WTrayIconPeer(target);
 500         targetCreatedPeer(target, peer);
 501         return peer;
 502     }
 503 
 504     public SystemTrayPeer createSystemTray(SystemTray target) {
 505         return new WSystemTrayPeer(target);
 506     }
 507 
 508     public boolean isTraySupported() {
 509         return true;
 510     }
 511 
 512     public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer()
 513       throws HeadlessException
 514     {
 515         return WKeyboardFocusManagerPeer.getInstance();
 516     }
 517 
 518     protected native void setDynamicLayoutNative(boolean b);
 519 
 520     public void setDynamicLayout(boolean b) {
 521         if (b == dynamicLayoutSetting) {
 522             return;
 523         }
 524 
 525         dynamicLayoutSetting = b;
 526         setDynamicLayoutNative(b);
 527     }
 528 
 529     protected boolean isDynamicLayoutSet() {
 530         return dynamicLayoutSetting;
 531     }
 532 
 533     /*
 534      * Called from lazilyLoadDynamicLayoutSupportedProperty because
 535      * Windows doesn't always send WM_SETTINGCHANGE when it should.
 536      */
 537     protected native boolean isDynamicLayoutSupportedNative();
 538 
 539     public boolean isDynamicLayoutActive() {
 540         return (isDynamicLayoutSet() && isDynamicLayoutSupported());
 541     }
 542 
 543     /**
 544      * Returns <code>true</code> if this frame state is supported.
 545      */
 546     public boolean isFrameStateSupported(int state) {
 547         switch (state) {
 548           case Frame.NORMAL:
 549           case Frame.ICONIFIED:
 550           case Frame.MAXIMIZED_BOTH:
 551               return true;
 552           default:
 553               return false;
 554         }
 555     }
 556 
 557     static native ColorModel makeColorModel();
 558     static ColorModel screenmodel;
 559 
 560     static ColorModel getStaticColorModel() {
 561         if (GraphicsEnvironment.isHeadless()) {
 562             throw new IllegalArgumentException();
 563         }
 564         if (config == null) {
 565             resetGC();
 566         }
 567         return config.getColorModel();
 568     }
 569 
 570     public ColorModel getColorModel() {
 571         return getStaticColorModel();
 572     }
 573 
 574     public Insets getScreenInsets(GraphicsConfiguration gc)
 575     {
 576         return getScreenInsets(((Win32GraphicsDevice) gc.getDevice()).getScreen());
 577     }
 578 
 579     public int getScreenResolution() {
 580         Win32GraphicsEnvironment ge = (Win32GraphicsEnvironment)
 581             GraphicsEnvironment.getLocalGraphicsEnvironment();
 582         return ge.getXResolution();
 583     }
 584     protected native int getScreenWidth();
 585     protected native int getScreenHeight();
 586     protected native Insets getScreenInsets(int screen);
 587 
 588 
 589     public FontMetrics getFontMetrics(Font font) {
 590         // This is an unsupported hack, but left in for a customer.
 591         // Do not remove.
 592         FontManager fm = FontManagerFactory.getInstance();
 593         if (fm instanceof SunFontManager
 594             && ((SunFontManager) fm).usePlatformFontMetrics()) {
 595             return WFontMetrics.getFontMetrics(font);
 596         }
 597         return super.getFontMetrics(font);
 598     }
 599 
 600     public FontPeer getFontPeer(String name, int style) {
 601         FontPeer retval = null;
 602         String lcName = name.toLowerCase();
 603         if (null != cacheFontPeer) {
 604             retval = (FontPeer)cacheFontPeer.get(lcName + style);
 605             if (null != retval) {
 606                 return retval;
 607             }
 608         }
 609         retval = new WFontPeer(name, style);
 610         if (retval != null) {
 611             if (null == cacheFontPeer) {
 612                 cacheFontPeer = new Hashtable(5, (float)0.9);
 613             }
 614             if (null != cacheFontPeer) {
 615                 cacheFontPeer.put(lcName + style, retval);
 616             }
 617         }
 618         return retval;
 619     }
 620 
 621     private native void nativeSync();
 622 
 623     public void sync() {
 624         // flush the GDI/DD buffers
 625         nativeSync();
 626         // now flush the OGL pipeline (this is a no-op if OGL is not enabled)
 627         OGLRenderQueue.sync();
 628         // now flush the D3D pipeline (this is a no-op if D3D is not enabled)
 629         D3DRenderQueue.sync();
 630     }
 631 
 632     public PrintJob getPrintJob(Frame frame, String doctitle,
 633                                 Properties props) {
 634         return getPrintJob(frame, doctitle, null, null);
 635     }
 636 
 637     public PrintJob getPrintJob(Frame frame, String doctitle,
 638                                 JobAttributes jobAttributes,
 639                                 PageAttributes pageAttributes)
 640     {
 641         if (frame == null) {
 642             throw new NullPointerException("frame must not be null");
 643         }
 644 
 645         PrintJob2D printJob = new PrintJob2D(frame, doctitle,
 646                                              jobAttributes, pageAttributes);
 647 
 648         if (printJob.printDialog() == false) {
 649             printJob = null;
 650         }
 651 
 652         return printJob;
 653     }
 654 
 655     public native void beep();
 656 
 657     public boolean getLockingKeyState(int key) {
 658         if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK ||
 659                key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) {
 660             throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState");
 661         }
 662         return getLockingKeyStateNative(key);
 663     }
 664 
 665     public native boolean getLockingKeyStateNative(int key);
 666 
 667     public void setLockingKeyState(int key, boolean on) {
 668         if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK ||
 669                key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) {
 670             throw new IllegalArgumentException("invalid key for Toolkit.setLockingKeyState");
 671         }
 672         setLockingKeyStateNative(key, on);
 673     }
 674 
 675     public native void setLockingKeyStateNative(int key, boolean on);
 676 
 677     public Clipboard getSystemClipboard() {
 678         SecurityManager security = System.getSecurityManager();
 679         if (security != null) {
 680           security.checkSystemClipboardAccess();
 681         }
 682         synchronized (this) {
 683             if (clipboard == null) {
 684                 clipboard = new WClipboard();
 685             }
 686         }
 687         return clipboard;
 688     }
 689 
 690     protected native void loadSystemColors(int[] systemColors);
 691 
 692     public static final Object targetToPeer(Object target) {
 693         return SunToolkit.targetToPeer(target);
 694     }
 695 
 696     public static final void targetDisposedPeer(Object target, Object peer) {
 697         SunToolkit.targetDisposedPeer(target, peer);
 698     }
 699 
 700     /**
 701      * Returns a new input method adapter descriptor for native input methods.
 702      */
 703     public InputMethodDescriptor getInputMethodAdapterDescriptor() {
 704         return new WInputMethodDescriptor();
 705     }
 706 
 707     /**
 708      * Returns a style map for the input method highlight.
 709      */
 710     public Map mapInputMethodHighlight(InputMethodHighlight highlight) {
 711         return WInputMethod.mapInputMethodHighlight(highlight);
 712     }
 713 
 714     /**
 715      * Returns whether enableInputMethods should be set to true for peered
 716      * TextComponent instances on this platform.
 717      */
 718     public boolean enableInputMethodsForTextComponent() {
 719         return true;
 720     }
 721 
 722     /**
 723      * Returns the default keyboard locale of the underlying operating system
 724      */
 725     public Locale getDefaultKeyboardLocale() {
 726         Locale locale = WInputMethod.getNativeLocale();
 727 
 728         if (locale == null) {
 729             return super.getDefaultKeyboardLocale();
 730         } else {
 731             return locale;
 732         }
 733     }
 734 
 735     /**
 736      * Returns a new custom cursor.
 737      */
 738     public Cursor createCustomCursor(Image cursor, Point hotSpot, String name)
 739         throws IndexOutOfBoundsException {
 740         return new WCustomCursor(cursor, hotSpot, name);
 741     }
 742 
 743     /**
 744      * Returns the supported cursor size (Win32 only has one).
 745      */
 746     public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) {
 747         return new Dimension(WCustomCursor.getCursorWidth(),
 748                              WCustomCursor.getCursorHeight());
 749     }
 750 
 751     public native int getMaximumCursorColors();
 752 
 753     static void paletteChanged() {
 754         ((Win32GraphicsEnvironment)GraphicsEnvironment
 755         .getLocalGraphicsEnvironment())
 756         .paletteChanged();
 757     }
 758 
 759     /*
 760      * Called from Toolkit native code when a WM_DISPLAYCHANGE occurs.
 761      * Have Win32GraphicsEnvironment execute the display change code on the
 762      * Event thread.
 763      */
 764     static public void displayChanged() {
 765         EventQueue.invokeLater(new Runnable() {
 766             public void run() {
 767                 ((Win32GraphicsEnvironment)GraphicsEnvironment
 768                 .getLocalGraphicsEnvironment())
 769                 .displayChanged();
 770             }
 771         });
 772     }
 773 
 774     /**
 775      * create the peer for a DragSourceContext
 776      */
 777 
 778     public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {
 779         return WDragSourceContextPeer.createDragSourceContextPeer(dge);
 780     }
 781 
 782     public <T extends DragGestureRecognizer> T
 783         createDragGestureRecognizer(Class<T> abstractRecognizerClass,
 784                                     DragSource ds, Component c, int srcActions,
 785                                     DragGestureListener dgl)
 786     {
 787         if (MouseDragGestureRecognizer.class.equals(abstractRecognizerClass))
 788             return (T)new WMouseDragGestureRecognizer(ds, c, srcActions, dgl);
 789         else
 790             return null;
 791     }
 792 
 793     /**
 794      *
 795      */
 796 
 797     private static final String prefix  = "DnD.Cursor.";
 798     private static final String postfix = ".32x32";
 799     private static final String awtPrefix  = "awt.";
 800     private static final String dndPrefix  = "DnD.";
 801 
 802     protected Object lazilyLoadDesktopProperty(String name) {
 803         if (name.startsWith(prefix)) {
 804             String cursorName = name.substring(prefix.length(), name.length()) + postfix;
 805 
 806             try {
 807                 return Cursor.getSystemCustomCursor(cursorName);
 808             } catch (AWTException awte) {
 809                 throw new RuntimeException("cannot load system cursor: " + cursorName, awte);
 810             }
 811         }
 812 
 813         if (name.equals("awt.dynamicLayoutSupported")) {
 814             return  Boolean.valueOf(isDynamicLayoutSupported());
 815         }
 816 
 817         if (WDesktopProperties.isWindowsProperty(name) ||
 818             name.startsWith(awtPrefix) || name.startsWith(dndPrefix))
 819         {
 820             synchronized(this) {
 821                 lazilyInitWProps();
 822                 return desktopProperties.get(name);
 823             }
 824         }
 825 
 826         return super.lazilyLoadDesktopProperty(name);
 827     }
 828 
 829     private synchronized void lazilyInitWProps() {
 830         if (wprops == null) {
 831             wprops = new WDesktopProperties(this);
 832             updateProperties();
 833         }
 834     }
 835 
 836     /*
 837      * Called from lazilyLoadDesktopProperty because Windows doesn't
 838      * always send WM_SETTINGCHANGE when it should.
 839      */
 840     private synchronized boolean isDynamicLayoutSupported() {
 841         boolean nativeDynamic = isDynamicLayoutSupportedNative();
 842         lazilyInitWProps();
 843         Boolean prop = (Boolean) desktopProperties.get("awt.dynamicLayoutSupported");
 844 
 845         if (log.isLoggable(PlatformLogger.FINER)) {
 846             log.finer("In WTK.isDynamicLayoutSupported()" +
 847                       "   nativeDynamic == " + nativeDynamic +
 848                       "   wprops.dynamic == " + prop);
 849         }
 850 
 851         if ((prop == null) || (nativeDynamic != prop.booleanValue())) {
 852             // We missed the WM_SETTINGCHANGE, so we pretend
 853             // we just got one - fire the propertyChange, etc.
 854             windowsSettingChange();
 855             return nativeDynamic;
 856         }
 857 
 858         return prop.booleanValue();
 859     }
 860 
 861     /*
 862      * Called from native toolkit code when WM_SETTINGCHANGE message received
 863      * Also called from lazilyLoadDynamicLayoutSupportedProperty because
 864      * Windows doesn't always send WM_SETTINGCHANGE when it should.
 865      */
 866     private void windowsSettingChange() {
 867         EventQueue.invokeLater(new Runnable() {
 868             @Override
 869             public void run() {
 870                 updateProperties();
 871             }
 872         });
 873     }
 874 
 875     private synchronized void updateProperties() {
 876         if (null == wprops) {
 877             // wprops has not been initialized, so we have nothing to update
 878             return;
 879         }
 880 
 881         Map<String, Object> props = wprops.getProperties();
 882         for (String propName : props.keySet()) {
 883             Object val = props.get(propName);
 884             if (log.isLoggable(PlatformLogger.FINER)) {
 885                 log.finer("changed " + propName + " to " + val);
 886             }
 887             setDesktopProperty(propName, val);
 888         }
 889     }
 890 
 891     public synchronized void addPropertyChangeListener(String name, PropertyChangeListener pcl) {
 892         if (name == null) {
 893             // See JavaDoc for the Toolkit.addPropertyChangeListener() method
 894             return;
 895         }
 896         if ( WDesktopProperties.isWindowsProperty(name)
 897              || name.startsWith(awtPrefix)
 898              || name.startsWith(dndPrefix))
 899         {
 900             // someone is interested in Windows-specific desktop properties
 901             // we should initialize wprops
 902             lazilyInitWProps();
 903         }
 904         super.addPropertyChangeListener(name, pcl);
 905     }
 906 
 907     /*
 908      * initialize only static props here and do not try to initialize props which depends on wprops,
 909      * this should be done in lazilyLoadDesktopProperty() only.
 910      */
 911     protected synchronized void initializeDesktopProperties() {
 912         desktopProperties.put("DnD.Autoscroll.initialDelay",
 913                               Integer.valueOf(50));
 914         desktopProperties.put("DnD.Autoscroll.interval",
 915                               Integer.valueOf(50));
 916         desktopProperties.put("DnD.isDragImageSupported",
 917                               Boolean.TRUE);
 918         desktopProperties.put("Shell.shellFolderManager",
 919                               "sun.awt.shell.Win32ShellFolderManager2");
 920     }
 921 
 922     /*
 923      * This returns the value for the desktop property "awt.font.desktophints"
 924      * This requires that the Windows properties have already been gathered.
 925      */
 926     protected synchronized RenderingHints getDesktopAAHints() {
 927         if (wprops == null) {
 928             return null;
 929         } else {
 930             return wprops.getDesktopAAHints();
 931         }
 932     }
 933 
 934     public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
 935         return (modalityType == null) ||
 936                (modalityType == Dialog.ModalityType.MODELESS) ||
 937                (modalityType == Dialog.ModalityType.DOCUMENT_MODAL) ||
 938                (modalityType == Dialog.ModalityType.APPLICATION_MODAL) ||
 939                (modalityType == Dialog.ModalityType.TOOLKIT_MODAL);
 940     }
 941 
 942     public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) {
 943         return (exclusionType == null) ||
 944                (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE) ||
 945                (exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) ||
 946                (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
 947     }
 948 
 949     public static WToolkit getWToolkit() {
 950         WToolkit toolkit = (WToolkit)Toolkit.getDefaultToolkit();
 951         return toolkit;
 952     }
 953 
 954     /**
 955      * There are two reasons why we don't use buffer per window when
 956      * Vista's DWM (aka Aero) is enabled:
 957      * - since with DWM all windows are already double-buffered, the application
 958      *   doesn't get expose events so we don't get to use our true back-buffer,
 959      *   wasting memory and performance (this is valid for both d3d and gdi
 960      *   pipelines)
 961      * - in some cases with buffer per window enabled it is possible for the
 962      *   paint manager to redirect rendering to the screen for some operations
 963      *   (like copyArea), and since bpw uses its own BufferStrategy the
 964      *   d3d onscreen rendering support is disabled and rendering goes through
 965      *   GDI. This doesn't work well with Vista's DWM since one
 966      *   can not perform GDI and D3D operations on the same surface
 967      *   (see 6630702 for more info)
 968      *
 969      * Note: even though DWM composition state can change during the lifetime
 970      * of the application it is a rare event, and it is more often that it
 971      * is temporarily disabled (because of some app) than it is getting
 972      * permanently enabled so we can live with this approach without the
 973      * complexity of dwm state listeners and such. This can be revisited if
 974      * proved otherwise.
 975      */
 976     @Override
 977     public boolean useBufferPerWindow() {
 978         return !Win32GraphicsEnvironment.isDWMCompositionEnabled();
 979     }
 980 
 981     public void grab(Window w) {
 982         if (w.getPeer() != null) {
 983             ((WWindowPeer)w.getPeer()).grab();
 984         }
 985     }
 986 
 987     public void ungrab(Window w) {
 988         if (w.getPeer() != null) {
 989            ((WWindowPeer)w.getPeer()).ungrab();
 990         }
 991     }
 992 
 993     public native boolean syncNativeQueue(final long timeout);
 994     public boolean isDesktopSupported() {
 995         return true;
 996     }
 997 
 998     public DesktopPeer createDesktopPeer(Desktop target) {
 999         return new WDesktopPeer();
1000     }
1001 
1002     public static native void setExtraMouseButtonsEnabledNative(boolean enable);
1003 
1004     public boolean areExtraMouseButtonsEnabled() throws HeadlessException {
1005         return areExtraMouseButtonsEnabled;
1006     }
1007 
1008     private native synchronized int getNumberOfButtonsImpl();
1009 
1010     @Override
1011     public int getNumberOfButtons(){
1012         if (numberOfButtons == 0) {
1013             numberOfButtons = getNumberOfButtonsImpl();
1014         }
1015         return (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons;
1016     }
1017 
1018     @Override
1019     public boolean isWindowOpacitySupported() {
1020         // supported in Win2K and later
1021         return true;
1022     }
1023 
1024     @Override
1025     public boolean isWindowShapingSupported() {
1026         return true;
1027     }
1028 
1029     @Override
1030     public boolean isWindowTranslucencySupported() {
1031         // supported in Win2K and later
1032         return true;
1033     }
1034 
1035     @Override
1036     public boolean isTranslucencyCapable(GraphicsConfiguration gc) {
1037         //XXX: worth checking if 8-bit? Anyway, it doesn't hurt.
1038         return true;
1039     }
1040 
1041     // On MS Windows one must use the peer.updateWindow() to implement
1042     // non-opaque windows.
1043     @Override
1044     public boolean needUpdateWindow() {
1045         return true;
1046     }
1047 }