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