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