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