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