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