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