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