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