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