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