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