1 /* 2 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt.windows; 27 28 import java.awt.peer.TaskbarPeer; 29 import java.awt.*; 30 import java.awt.im.InputMethodHighlight; 31 import java.awt.im.spi.InputMethodDescriptor; 32 import java.awt.image.*; 33 import java.awt.peer.*; 34 import java.awt.event.KeyEvent; 35 import java.awt.datatransfer.Clipboard; 36 import java.awt.TrayIcon; 37 import java.beans.PropertyChangeListener; 38 import java.security.AccessController; 39 import java.security.PrivilegedAction; 40 41 import sun.awt.AWTAccessor; 42 import sun.awt.AppContext; 43 import sun.awt.AWTAutoShutdown; 44 import sun.awt.AWTPermissions; 45 import sun.awt.AppContext; 46 import sun.awt.LightweightFrame; 47 import sun.awt.SunToolkit; 48 import sun.awt.util.ThreadGroupUtils; 49 import sun.awt.Win32GraphicsDevice; 50 import sun.awt.Win32GraphicsEnvironment; 51 import sun.awt.datatransfer.DataTransferer; 52 import sun.java2d.d3d.D3DRenderQueue; 53 import sun.java2d.opengl.OGLRenderQueue; 54 55 import sun.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.awt.util.PerformanceLogger; 71 import sun.font.FontManager; 72 import sun.font.FontManagerFactory; 73 import sun.font.SunFontManager; 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 Thread(rootTG, this, name, 0, false); 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 Thread( 286 ThreadGroupUtils.getRootThreadGroup(), this::shutdown, 287 "ToolkitShutdown", 0, false); 288 shutdown.setContextClassLoader(null); 289 Runtime.getRuntime().addShutdownHook(shutdown); 290 return null; 291 }); 292 } 293 294 @Override 295 public void run() { 296 AccessController.doPrivileged((PrivilegedAction<Void>) () -> { 297 Thread.currentThread().setContextClassLoader(null); 298 Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 1); 299 return null; 300 }); 301 302 boolean startPump = init(); 303 304 if (startPump) { 305 registerShutdownHook(); 306 } 307 308 synchronized(this) { 309 inited = true; 310 notifyAll(); 311 } 312 313 if (startPump) { 314 eventLoop(); // will Dispose Toolkit when shutdown hook executes 315 } 316 } 317 318 /* 319 * eventLoop() begins the native message pump which retrieves and processes 320 * native events. 321 * 322 * When shutdown() is called by the ShutdownHook added in run(), a 323 * WM_QUIT message is posted to the Toolkit thread indicating that 324 * eventLoop() should Dispose the toolkit and exit. 325 */ 326 private native boolean init(); 327 private boolean inited = false; 328 329 private native void eventLoop(); 330 private native void shutdown(); 331 332 /* 333 * Instead of blocking the "AWT-Windows" thread uselessly on a semaphore, 334 * use these functions. startSecondaryEventLoop() corresponds to wait() 335 * and quitSecondaryEventLoop() corresponds to notify. 336 * 337 * These functions simulate blocking while allowing the AWT to continue 338 * processing native events, eliminating a potential deadlock situation 339 * with SendMessage. 340 * 341 * WARNING: startSecondaryEventLoop must only be called from the "AWT- 342 * Windows" thread. 343 */ 344 static native void startSecondaryEventLoop(); 345 static native void quitSecondaryEventLoop(); 346 347 /* 348 * Create peer objects. 349 */ 350 351 @Override 352 public ButtonPeer createButton(Button target) { 353 ButtonPeer peer = new WButtonPeer(target); 354 targetCreatedPeer(target, peer); 355 return peer; 356 } 357 358 @Override 359 public TextFieldPeer createTextField(TextField target) { 360 TextFieldPeer peer = new WTextFieldPeer(target); 361 targetCreatedPeer(target, peer); 362 return peer; 363 } 364 365 @Override 366 public LabelPeer createLabel(Label target) { 367 LabelPeer peer = new WLabelPeer(target); 368 targetCreatedPeer(target, peer); 369 return peer; 370 } 371 372 @Override 373 public ListPeer createList(List target) { 374 ListPeer peer = new WListPeer(target); 375 targetCreatedPeer(target, peer); 376 return peer; 377 } 378 379 @Override 380 public CheckboxPeer createCheckbox(Checkbox target) { 381 CheckboxPeer peer = new WCheckboxPeer(target); 382 targetCreatedPeer(target, peer); 383 return peer; 384 } 385 386 @Override 387 public ScrollbarPeer createScrollbar(Scrollbar target) { 388 ScrollbarPeer peer = new WScrollbarPeer(target); 389 targetCreatedPeer(target, peer); 390 return peer; 391 } 392 393 @Override 394 public ScrollPanePeer createScrollPane(ScrollPane target) { 395 ScrollPanePeer peer = new WScrollPanePeer(target); 396 targetCreatedPeer(target, peer); 397 return peer; 398 } 399 400 @Override 401 public TextAreaPeer createTextArea(TextArea target) { 402 TextAreaPeer peer = new WTextAreaPeer(target); 403 targetCreatedPeer(target, peer); 404 return peer; 405 } 406 407 @Override 408 public ChoicePeer createChoice(Choice target) { 409 ChoicePeer peer = new WChoicePeer(target); 410 targetCreatedPeer(target, peer); 411 return peer; 412 } 413 414 @Override 415 public FramePeer createFrame(Frame target) { 416 FramePeer peer = new WFramePeer(target); 417 targetCreatedPeer(target, peer); 418 return peer; 419 } 420 421 @Override 422 public FramePeer createLightweightFrame(LightweightFrame target) { 423 FramePeer peer = new WLightweightFramePeer(target); 424 targetCreatedPeer(target, peer); 425 return peer; 426 } 427 428 @Override 429 public CanvasPeer createCanvas(Canvas target) { 430 CanvasPeer peer = new WCanvasPeer(target); 431 targetCreatedPeer(target, peer); 432 return peer; 433 } 434 435 @Override 436 public void disableBackgroundErase(Canvas canvas) { 437 WCanvasPeer peer = AWTAccessor.getComponentAccessor().getPeer(canvas); 438 if (peer == null) { 439 throw new IllegalStateException("Canvas must have a valid peer"); 440 } 441 peer.disableBackgroundErase(); 442 } 443 444 @Override 445 public PanelPeer createPanel(Panel target) { 446 PanelPeer peer = new WPanelPeer(target); 447 targetCreatedPeer(target, peer); 448 return peer; 449 } 450 451 @Override 452 public WindowPeer createWindow(Window target) { 453 WindowPeer peer = new WWindowPeer(target); 454 targetCreatedPeer(target, peer); 455 return peer; 456 } 457 458 @Override 459 public DialogPeer createDialog(Dialog target) { 460 DialogPeer peer = new WDialogPeer(target); 461 targetCreatedPeer(target, peer); 462 return peer; 463 } 464 465 @Override 466 public FileDialogPeer createFileDialog(FileDialog target) { 467 FileDialogPeer peer = new WFileDialogPeer(target); 468 targetCreatedPeer(target, peer); 469 return peer; 470 } 471 472 @Override 473 public MenuBarPeer createMenuBar(MenuBar target) { 474 MenuBarPeer peer = new WMenuBarPeer(target); 475 targetCreatedPeer(target, peer); 476 return peer; 477 } 478 479 @Override 480 public MenuPeer createMenu(Menu target) { 481 MenuPeer peer = new WMenuPeer(target); 482 targetCreatedPeer(target, peer); 483 return peer; 484 } 485 486 @Override 487 public PopupMenuPeer createPopupMenu(PopupMenu target) { 488 PopupMenuPeer peer = new WPopupMenuPeer(target); 489 targetCreatedPeer(target, peer); 490 return peer; 491 } 492 493 @Override 494 public MenuItemPeer createMenuItem(MenuItem target) { 495 MenuItemPeer peer = new WMenuItemPeer(target); 496 targetCreatedPeer(target, peer); 497 return peer; 498 } 499 500 @Override 501 public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) { 502 CheckboxMenuItemPeer peer = new WCheckboxMenuItemPeer(target); 503 targetCreatedPeer(target, peer); 504 return peer; 505 } 506 507 @Override 508 public RobotPeer createRobot(Robot target, GraphicsDevice screen) { 509 // (target is unused for now) 510 // Robot's don't need to go in the peer map since 511 // they're not Component's 512 return new WRobotPeer(screen); 513 } 514 515 public WEmbeddedFramePeer createEmbeddedFrame(WEmbeddedFrame target) { 516 WEmbeddedFramePeer peer = new WEmbeddedFramePeer(target); 517 targetCreatedPeer(target, peer); 518 return peer; 519 } 520 521 WPrintDialogPeer createWPrintDialog(WPrintDialog target) { 522 WPrintDialogPeer peer = new WPrintDialogPeer(target); 523 targetCreatedPeer(target, peer); 524 return peer; 525 } 526 527 WPageDialogPeer createWPageDialog(WPageDialog target) { 528 WPageDialogPeer peer = new WPageDialogPeer(target); 529 targetCreatedPeer(target, peer); 530 return peer; 531 } 532 533 @Override 534 public TrayIconPeer createTrayIcon(TrayIcon target) { 535 WTrayIconPeer peer = new WTrayIconPeer(target); 536 targetCreatedPeer(target, peer); 537 return peer; 538 } 539 540 @Override 541 public SystemTrayPeer createSystemTray(SystemTray target) { 542 return new WSystemTrayPeer(target); 543 } 544 545 @Override 546 public boolean isTraySupported() { 547 return true; 548 } 549 550 @Override 551 public DataTransferer getDataTransferer() { 552 return WDataTransferer.getInstanceImpl(); 553 } 554 555 @Override 556 public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() 557 throws HeadlessException 558 { 559 return WKeyboardFocusManagerPeer.getInstance(); 560 } 561 562 private static WMouseInfoPeer wPeer = null; 563 564 @Override 565 public synchronized MouseInfoPeer getMouseInfoPeer() { 566 if (wPeer == null) { 567 wPeer = new WMouseInfoPeer(); 568 } 569 return wPeer; 570 } 571 572 private native void setDynamicLayoutNative(boolean b); 573 574 @Override 575 public void setDynamicLayout(boolean b) { 576 if (b == dynamicLayoutSetting) { 577 return; 578 } 579 580 dynamicLayoutSetting = b; 581 setDynamicLayoutNative(b); 582 } 583 584 @Override 585 protected boolean isDynamicLayoutSet() { 586 return dynamicLayoutSetting; 587 } 588 589 /* 590 * Called from lazilyLoadDynamicLayoutSupportedProperty because 591 * Windows doesn't always send WM_SETTINGCHANGE when it should. 592 */ 593 private native boolean isDynamicLayoutSupportedNative(); 594 595 @Override 596 public boolean isDynamicLayoutActive() { 597 return (isDynamicLayoutSet() && isDynamicLayoutSupported()); 598 } 599 600 /** 601 * Returns {@code true} if this frame state is supported. 602 */ 603 @Override 604 public boolean isFrameStateSupported(int state) { 605 switch (state) { 606 case Frame.NORMAL: 607 case Frame.ICONIFIED: 608 case Frame.MAXIMIZED_BOTH: 609 return true; 610 default: 611 return false; 612 } 613 } 614 615 static native ColorModel makeColorModel(); 616 static ColorModel screenmodel; 617 618 static ColorModel getStaticColorModel() { 619 if (GraphicsEnvironment.isHeadless()) { 620 throw new IllegalArgumentException(); 621 } 622 if (config == null) { 623 resetGC(); 624 } 625 return config.getColorModel(); 626 } 627 628 @Override 629 public ColorModel getColorModel() { 630 return getStaticColorModel(); 631 } 632 633 @Override 634 public Insets getScreenInsets(GraphicsConfiguration gc) 635 { 636 return getScreenInsets(((Win32GraphicsDevice) gc.getDevice()).getScreen()); 637 } 638 639 @Override 640 public int getScreenResolution() { 641 Win32GraphicsEnvironment ge = (Win32GraphicsEnvironment) 642 GraphicsEnvironment.getLocalGraphicsEnvironment(); 643 return ge.getXResolution(); 644 } 645 646 @Override 647 protected int getScreenWidth() { 648 return GraphicsEnvironment.getLocalGraphicsEnvironment() 649 .getDefaultScreenDevice().getDefaultConfiguration() 650 .getBounds().width; 651 } 652 653 @Override 654 protected int getScreenHeight() { 655 return GraphicsEnvironment.getLocalGraphicsEnvironment() 656 .getDefaultScreenDevice().getDefaultConfiguration() 657 .getBounds().height; 658 } 659 660 private native Insets getScreenInsets(int screen); 661 662 663 @Override 664 public FontMetrics getFontMetrics(Font font) { 665 // This is an unsupported hack, but left in for a customer. 666 // Do not remove. 667 FontManager fm = FontManagerFactory.getInstance(); 668 if (fm instanceof SunFontManager 669 && ((SunFontManager) fm).usePlatformFontMetrics()) { 670 return WFontMetrics.getFontMetrics(font); 671 } 672 return super.getFontMetrics(font); 673 } 674 675 @Override 676 public FontPeer getFontPeer(String name, int style) { 677 FontPeer retval = null; 678 String lcName = name.toLowerCase(); 679 if (null != cacheFontPeer) { 680 retval = cacheFontPeer.get(lcName + style); 681 if (null != retval) { 682 return retval; 683 } 684 } 685 retval = new WFontPeer(name, style); 686 if (retval != null) { 687 if (null == cacheFontPeer) { 688 cacheFontPeer = new Hashtable<>(5, 0.9f); 689 } 690 if (null != cacheFontPeer) { 691 cacheFontPeer.put(lcName + style, retval); 692 } 693 } 694 return retval; 695 } 696 697 private native void nativeSync(); 698 699 @Override 700 public void sync() { 701 // flush the GDI/DD buffers 702 nativeSync(); 703 // now flush the OGL pipeline (this is a no-op if OGL is not enabled) 704 OGLRenderQueue.sync(); 705 // now flush the D3D pipeline (this is a no-op if D3D is not enabled) 706 D3DRenderQueue.sync(); 707 } 708 709 @Override 710 public PrintJob getPrintJob(Frame frame, String doctitle, 711 Properties props) { 712 return getPrintJob(frame, doctitle, null, null); 713 } 714 715 @Override 716 public PrintJob getPrintJob(Frame frame, String doctitle, 717 JobAttributes jobAttributes, 718 PageAttributes pageAttributes) 719 { 720 if (frame == null) { 721 throw new NullPointerException("frame must not be null"); 722 } 723 724 PrintJob2D printJob = new PrintJob2D(frame, doctitle, 725 jobAttributes, pageAttributes); 726 727 if (printJob.printDialog() == false) { 728 printJob = null; 729 } 730 731 return printJob; 732 } 733 734 @Override 735 public native void beep(); 736 737 @Override 738 public boolean getLockingKeyState(int key) { 739 if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK || 740 key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) { 741 throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState"); 742 } 743 return getLockingKeyStateNative(key); 744 } 745 746 private native boolean getLockingKeyStateNative(int key); 747 748 @Override 749 public void setLockingKeyState(int key, boolean on) { 750 if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK || 751 key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) { 752 throw new IllegalArgumentException("invalid key for Toolkit.setLockingKeyState"); 753 } 754 setLockingKeyStateNative(key, on); 755 } 756 757 private native void setLockingKeyStateNative(int key, boolean on); 758 759 @Override 760 public Clipboard getSystemClipboard() { 761 SecurityManager security = System.getSecurityManager(); 762 if (security != null) { 763 security.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION); 764 } 765 synchronized (this) { 766 if (clipboard == null) { 767 clipboard = new WClipboard(); 768 } 769 } 770 return clipboard; 771 } 772 773 @Override 774 protected native void loadSystemColors(int[] systemColors); 775 776 public static Object targetToPeer(Object target) { 777 return SunToolkit.targetToPeer(target); 778 } 779 780 public static void targetDisposedPeer(Object target, Object peer) { 781 SunToolkit.targetDisposedPeer(target, peer); 782 } 783 784 /** 785 * Returns a new input method adapter descriptor for native input methods. 786 */ 787 @Override 788 public InputMethodDescriptor getInputMethodAdapterDescriptor() { 789 return new WInputMethodDescriptor(); 790 } 791 792 /** 793 * Returns a style map for the input method highlight. 794 */ 795 @Override 796 public Map<java.awt.font.TextAttribute,?> mapInputMethodHighlight( 797 InputMethodHighlight highlight) 798 { 799 return WInputMethod.mapInputMethodHighlight(highlight); 800 } 801 802 /** 803 * Returns whether enableInputMethods should be set to true for peered 804 * TextComponent instances on this platform. 805 */ 806 @Override 807 public boolean enableInputMethodsForTextComponent() { 808 return true; 809 } 810 811 /** 812 * Returns the default keyboard locale of the underlying operating system 813 */ 814 @Override 815 public Locale getDefaultKeyboardLocale() { 816 Locale locale = WInputMethod.getNativeLocale(); 817 818 if (locale == null) { 819 return super.getDefaultKeyboardLocale(); 820 } else { 821 return locale; 822 } 823 } 824 825 /** 826 * Returns a new custom cursor. 827 */ 828 @Override 829 public Cursor createCustomCursor(Image cursor, Point hotSpot, String name) 830 throws IndexOutOfBoundsException { 831 return new WCustomCursor(cursor, hotSpot, name); 832 } 833 834 /** 835 * Returns the supported cursor size (Win32 only has one). 836 */ 837 @Override 838 public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) { 839 return new Dimension(WCustomCursor.getCursorWidth(), 840 WCustomCursor.getCursorHeight()); 841 } 842 843 @Override 844 public native int getMaximumCursorColors(); 845 846 static void paletteChanged() { 847 ((Win32GraphicsEnvironment)GraphicsEnvironment 848 .getLocalGraphicsEnvironment()) 849 .paletteChanged(); 850 } 851 852 /* 853 * Called from Toolkit native code when a WM_DISPLAYCHANGE occurs. 854 * Have Win32GraphicsEnvironment execute the display change code on the 855 * Event thread. 856 */ 857 public static void displayChanged() { 858 EventQueue.invokeLater(new Runnable() { 859 @Override 860 public void run() { 861 ((Win32GraphicsEnvironment)GraphicsEnvironment 862 .getLocalGraphicsEnvironment()) 863 .displayChanged(); 864 } 865 }); 866 } 867 868 /** 869 * create the peer for a DragSourceContext 870 */ 871 872 @Override 873 public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { 874 final LightweightFrame f = SunToolkit.getLightweightFrame(dge.getComponent()); 875 if (f != null) { 876 return f.createDragSourceContextPeer(dge); 877 } 878 879 return WDragSourceContextPeer.createDragSourceContextPeer(dge); 880 } 881 882 @Override 883 @SuppressWarnings("unchecked") 884 public <T extends DragGestureRecognizer> T 885 createDragGestureRecognizer(Class<T> abstractRecognizerClass, 886 DragSource ds, Component c, int srcActions, 887 DragGestureListener dgl) 888 { 889 final LightweightFrame f = SunToolkit.getLightweightFrame(c); 890 if (f != null) { 891 return f.createDragGestureRecognizer(abstractRecognizerClass, ds, c, srcActions, dgl); 892 } 893 894 if (MouseDragGestureRecognizer.class.equals(abstractRecognizerClass)) 895 return (T)new WMouseDragGestureRecognizer(ds, c, srcActions, dgl); 896 else 897 return null; 898 } 899 900 /** 901 * 902 */ 903 904 private static final String prefix = "DnD.Cursor."; 905 private static final String postfix = ".32x32"; 906 private static final String awtPrefix = "awt."; 907 private static final String dndPrefix = "DnD."; 908 909 @Override 910 protected Object lazilyLoadDesktopProperty(String name) { 911 if (name.startsWith(prefix)) { 912 String cursorName = name.substring(prefix.length(), name.length()) + postfix; 913 914 try { 915 return Cursor.getSystemCustomCursor(cursorName); 916 } catch (AWTException awte) { 917 throw new RuntimeException("cannot load system cursor: " + cursorName, awte); 918 } 919 } 920 921 if (name.equals("awt.dynamicLayoutSupported")) { 922 return Boolean.valueOf(isDynamicLayoutSupported()); 923 } 924 925 if (WDesktopProperties.isWindowsProperty(name) || 926 name.startsWith(awtPrefix) || name.startsWith(dndPrefix)) 927 { 928 synchronized(this) { 929 lazilyInitWProps(); 930 return desktopProperties.get(name); 931 } 932 } 933 934 return super.lazilyLoadDesktopProperty(name); 935 } 936 937 private synchronized void lazilyInitWProps() { 938 if (wprops == null) { 939 wprops = new WDesktopProperties(this); 940 updateProperties(wprops.getProperties()); 941 } 942 } 943 944 /* 945 * Called from lazilyLoadDesktopProperty because Windows doesn't 946 * always send WM_SETTINGCHANGE when it should. 947 */ 948 private synchronized boolean isDynamicLayoutSupported() { 949 boolean nativeDynamic = isDynamicLayoutSupportedNative(); 950 lazilyInitWProps(); 951 Boolean prop = (Boolean) desktopProperties.get("awt.dynamicLayoutSupported"); 952 953 if (log.isLoggable(PlatformLogger.Level.FINER)) { 954 log.finer("In WTK.isDynamicLayoutSupported()" + 955 " nativeDynamic == " + nativeDynamic + 956 " wprops.dynamic == " + prop); 957 } 958 959 if ((prop == null) || (nativeDynamic != prop.booleanValue())) { 960 // We missed the WM_SETTINGCHANGE, so we pretend 961 // we just got one - fire the propertyChange, etc. 962 windowsSettingChange(); 963 return nativeDynamic; 964 } 965 966 return prop.booleanValue(); 967 } 968 969 /* 970 * Called from native toolkit code when WM_SETTINGCHANGE message received 971 * Also called from lazilyLoadDynamicLayoutSupportedProperty because 972 * Windows doesn't always send WM_SETTINGCHANGE when it should. 973 */ 974 private void windowsSettingChange() { 975 // JDK-8039383: Have to update the value of XPSTYLE_THEME_ACTIVE property 976 // as soon as possible to prevent NPE and other errors because theme data 977 // has become unavailable. 978 final Map<String, Object> props = getWProps(); 979 if (props == null) { 980 // props has not been initialized, so we have nothing to update 981 return; 982 } 983 984 updateXPStyleEnabled(props.get(XPSTYLE_THEME_ACTIVE)); 985 986 if (AppContext.getAppContext() == null) { 987 // We cannot post the update to any EventQueue. Listeners will 988 // be called on EDTs by DesktopPropertyChangeSupport 989 updateProperties(props); 990 } else { 991 // Cannot update on Toolkit thread. 992 // DesktopPropertyChangeSupport will call listeners on Toolkit 993 // thread if it has AppContext (standalone mode) 994 EventQueue.invokeLater(() -> updateProperties(props)); 995 } 996 } 997 998 private synchronized void updateProperties(final Map<String, Object> props) { 999 if (null == props) { 1000 return; 1001 } 1002 1003 updateXPStyleEnabled(props.get(XPSTYLE_THEME_ACTIVE)); 1004 1005 for (String propName : props.keySet()) { 1006 Object val = props.get(propName); 1007 if (log.isLoggable(PlatformLogger.Level.FINER)) { 1008 log.finer("changed " + propName + " to " + val); 1009 } 1010 setDesktopProperty(propName, val); 1011 } 1012 } 1013 1014 private synchronized Map<String, Object> getWProps() { 1015 return (wprops != null) ? wprops.getProperties() : null; 1016 } 1017 1018 private void updateXPStyleEnabled(final Object dskProp) { 1019 ThemeReader.xpStyleEnabled = Boolean.TRUE.equals(dskProp); 1020 } 1021 1022 @Override 1023 public synchronized void addPropertyChangeListener(String name, PropertyChangeListener pcl) { 1024 if (name == null) { 1025 // See JavaDoc for the Toolkit.addPropertyChangeListener() method 1026 return; 1027 } 1028 if ( WDesktopProperties.isWindowsProperty(name) 1029 || name.startsWith(awtPrefix) 1030 || name.startsWith(dndPrefix)) 1031 { 1032 // someone is interested in Windows-specific desktop properties 1033 // we should initialize wprops 1034 lazilyInitWProps(); 1035 } 1036 super.addPropertyChangeListener(name, pcl); 1037 } 1038 1039 /* 1040 * initialize only static props here and do not try to initialize props which depends on wprops, 1041 * this should be done in lazilyLoadDesktopProperty() only. 1042 */ 1043 @Override 1044 protected synchronized void initializeDesktopProperties() { 1045 desktopProperties.put("DnD.Autoscroll.initialDelay", 1046 Integer.valueOf(50)); 1047 desktopProperties.put("DnD.Autoscroll.interval", 1048 Integer.valueOf(50)); 1049 desktopProperties.put("DnD.isDragImageSupported", 1050 Boolean.TRUE); 1051 desktopProperties.put("Shell.shellFolderManager", 1052 "sun.awt.shell.Win32ShellFolderManager2"); 1053 } 1054 1055 /* 1056 * This returns the value for the desktop property "awt.font.desktophints" 1057 * This requires that the Windows properties have already been gathered. 1058 */ 1059 @Override 1060 protected synchronized RenderingHints getDesktopAAHints() { 1061 if (wprops == null) { 1062 return null; 1063 } else { 1064 return wprops.getDesktopAAHints(); 1065 } 1066 } 1067 1068 @Override 1069 public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) { 1070 return (modalityType == null) || 1071 (modalityType == Dialog.ModalityType.MODELESS) || 1072 (modalityType == Dialog.ModalityType.DOCUMENT_MODAL) || 1073 (modalityType == Dialog.ModalityType.APPLICATION_MODAL) || 1074 (modalityType == Dialog.ModalityType.TOOLKIT_MODAL); 1075 } 1076 1077 @Override 1078 public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) { 1079 return (exclusionType == null) || 1080 (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE) || 1081 (exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) || 1082 (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE); 1083 } 1084 1085 public static WToolkit getWToolkit() { 1086 WToolkit toolkit = (WToolkit)Toolkit.getDefaultToolkit(); 1087 return toolkit; 1088 } 1089 1090 /** 1091 * There are two reasons why we don't use buffer per window when 1092 * Vista's DWM (aka Aero) is enabled: 1093 * - since with DWM all windows are already double-buffered, the application 1094 * doesn't get expose events so we don't get to use our true back-buffer, 1095 * wasting memory and performance (this is valid for both d3d and gdi 1096 * pipelines) 1097 * - in some cases with buffer per window enabled it is possible for the 1098 * paint manager to redirect rendering to the screen for some operations 1099 * (like copyArea), and since bpw uses its own BufferStrategy the 1100 * d3d onscreen rendering support is disabled and rendering goes through 1101 * GDI. This doesn't work well with Vista's DWM since one 1102 * can not perform GDI and D3D operations on the same surface 1103 * (see 6630702 for more info) 1104 * 1105 * Note: even though DWM composition state can change during the lifetime 1106 * of the application it is a rare event, and it is more often that it 1107 * is temporarily disabled (because of some app) than it is getting 1108 * permanently enabled so we can live with this approach without the 1109 * complexity of dwm state listeners and such. This can be revisited if 1110 * proved otherwise. 1111 */ 1112 @Override 1113 public boolean useBufferPerWindow() { 1114 return !Win32GraphicsEnvironment.isDWMCompositionEnabled(); 1115 } 1116 1117 @Override 1118 public void grab(Window w) { 1119 final Object peer = AWTAccessor.getComponentAccessor().getPeer(w); 1120 if (peer != null) { 1121 ((WWindowPeer) peer).grab(); 1122 } 1123 } 1124 1125 @Override 1126 public void ungrab(Window w) { 1127 final Object peer = AWTAccessor.getComponentAccessor().getPeer(w); 1128 if (peer != null) { 1129 ((WWindowPeer) peer).ungrab(); 1130 } 1131 } 1132 1133 @Override 1134 public native boolean syncNativeQueue(final long timeout); 1135 1136 @Override 1137 public boolean isDesktopSupported() { 1138 return true; 1139 } 1140 1141 @Override 1142 public DesktopPeer createDesktopPeer(Desktop target) { 1143 return new WDesktopPeer(); 1144 } 1145 1146 @Override 1147 public boolean isTaskbarSupported() { 1148 return WTaskbarPeer.isTaskbarSupported(); 1149 } 1150 1151 @Override 1152 public TaskbarPeer createTaskbarPeer(Taskbar target) { 1153 return new WTaskbarPeer(); 1154 } 1155 1156 private static native void setExtraMouseButtonsEnabledNative(boolean enable); 1157 1158 @Override 1159 public boolean areExtraMouseButtonsEnabled() throws HeadlessException { 1160 return areExtraMouseButtonsEnabled; 1161 } 1162 1163 private synchronized native int getNumberOfButtonsImpl(); 1164 1165 @Override 1166 public int getNumberOfButtons(){ 1167 if (numberOfButtons == 0) { 1168 numberOfButtons = getNumberOfButtonsImpl(); 1169 } 1170 return (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons; 1171 } 1172 1173 @Override 1174 public boolean isWindowOpacitySupported() { 1175 // supported in Win2K and later 1176 return true; 1177 } 1178 1179 @Override 1180 public boolean isWindowShapingSupported() { 1181 return true; 1182 } 1183 1184 @Override 1185 public boolean isWindowTranslucencySupported() { 1186 // supported in Win2K and later 1187 return true; 1188 } 1189 1190 @Override 1191 public boolean isTranslucencyCapable(GraphicsConfiguration gc) { 1192 //XXX: worth checking if 8-bit? Anyway, it doesn't hurt. 1193 return true; 1194 } 1195 1196 // On MS Windows one must use the peer.updateWindow() to implement 1197 // non-opaque windows. 1198 @Override 1199 public boolean needUpdateWindow() { 1200 return true; 1201 } 1202 } --- EOF ---