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