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