1 /* 2 * Copyright (c) 1996, 2010, 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 synchronized (this) { 232 // Fix for bug #4046430 -- Race condition 233 // where notifyAll can be called before 234 // the "AWT-Windows" thread's parent thread is 235 // waiting, resulting in a deadlock on startup. 236 237 /* 238 * Fix for 4701990. 239 * AWTAutoShutdown state must be changed before the toolkit thread 240 * starts to avoid race condition. 241 */ 242 AWTAutoShutdown.notifyToolkitThreadBusy(); 243 244 if (!startToolkitThread(this)) { 245 Thread toolkitThread = new Thread(this, "AWT-Windows"); 246 toolkitThread.setDaemon(true); 247 toolkitThread.start(); 248 } 249 250 try { 251 wait(); 252 } 253 catch (InterruptedException x) { 254 } 255 } 256 SunToolkit.setDataTransfererClassName(DATA_TRANSFERER_CLASS_NAME); 257 258 // Enabled "live resizing" by default. It remains controlled 259 // by the native system though. 260 setDynamicLayout(true); 261 262 areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons", "true")); 263 //set system property if not yet assigned 264 System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled); 265 setExtraMouseButtonsEnabledNative(areExtraMouseButtonsEnabled); 266 } 267 268 public void run() { 269 Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1); 270 boolean startPump = init(); 271 272 if (startPump) { 273 AccessController.doPrivileged(new PrivilegedAction() { 274 public Object run() { 275 ThreadGroup currentTG = 276 Thread.currentThread().getThreadGroup(); 277 ThreadGroup parentTG = currentTG.getParent(); 278 while (parentTG != null) { 279 currentTG = parentTG; 280 parentTG = currentTG.getParent(); 281 } 282 Thread shutdown = new Thread(currentTG, new Runnable() { 283 public void run() { 284 shutdown(); 285 } 286 }); 287 shutdown.setContextClassLoader(null); 288 Runtime.getRuntime().addShutdownHook(shutdown); 289 return null; 290 } 291 }); 292 } 293 294 synchronized(this) { 295 notifyAll(); 296 } 297 298 if (startPump) { 299 eventLoop(); // will Dispose Toolkit when shutdown hook executes 300 } 301 } 302 303 /* 304 * eventLoop() begins the native message pump which retrieves and processes 305 * native events. 306 * 307 * When shutdown() is called by the ShutdownHook added in run(), a 308 * WM_QUIT message is posted to the Toolkit thread indicating that 309 * eventLoop() should Dispose the toolkit and exit. 310 */ 311 private native boolean init(); 312 private native void eventLoop(); 313 private native void shutdown(); 314 315 /* 316 * Instead of blocking the "AWT-Windows" thread uselessly on a semaphore, 317 * use these functions. startSecondaryEventLoop() corresponds to wait() 318 * and quitSecondaryEventLoop() corresponds to notify. 319 * 320 * These functions simulate blocking while allowing the AWT to continue 321 * processing native events, eliminating a potential deadlock situation 322 * with SendMessage. 323 * 324 * WARNING: startSecondaryEventLoop must only be called from the "AWT- 325 * Windows" thread. 326 */ 327 public static native void startSecondaryEventLoop(); 328 public static native void quitSecondaryEventLoop(); 329 330 /* 331 * Create peer objects. 332 */ 333 334 public ButtonPeer createButton(Button target) { 335 ButtonPeer peer = new WButtonPeer(target); 336 targetCreatedPeer(target, peer); 337 return peer; 338 } 339 340 public TextFieldPeer createTextField(TextField target) { 341 TextFieldPeer peer = new WTextFieldPeer(target); 342 targetCreatedPeer(target, peer); 343 return peer; 344 } 345 346 public LabelPeer createLabel(Label target) { 347 LabelPeer peer = new WLabelPeer(target); 348 targetCreatedPeer(target, peer); 349 return peer; 350 } 351 352 public ListPeer createList(List target) { 353 ListPeer peer = new WListPeer(target); 354 targetCreatedPeer(target, peer); 355 return peer; 356 } 357 358 public CheckboxPeer createCheckbox(Checkbox target) { 359 CheckboxPeer peer = new WCheckboxPeer(target); 360 targetCreatedPeer(target, peer); 361 return peer; 362 } 363 364 public ScrollbarPeer createScrollbar(Scrollbar target) { 365 ScrollbarPeer peer = new WScrollbarPeer(target); 366 targetCreatedPeer(target, peer); 367 return peer; 368 } 369 370 public ScrollPanePeer createScrollPane(ScrollPane target) { 371 ScrollPanePeer peer = new WScrollPanePeer(target); 372 targetCreatedPeer(target, peer); 373 return peer; 374 } 375 376 public TextAreaPeer createTextArea(TextArea target) { 377 TextAreaPeer peer = new WTextAreaPeer(target); 378 targetCreatedPeer(target, peer); 379 return peer; 380 } 381 382 public ChoicePeer createChoice(Choice target) { 383 ChoicePeer peer = new WChoicePeer(target); 384 targetCreatedPeer(target, peer); 385 return peer; 386 } 387 388 public FramePeer createFrame(Frame target) { 389 FramePeer peer = new WFramePeer(target); 390 targetCreatedPeer(target, peer); 391 return peer; 392 } 393 394 public CanvasPeer createCanvas(Canvas target) { 395 CanvasPeer peer = new WCanvasPeer(target); 396 targetCreatedPeer(target, peer); 397 return peer; 398 } 399 400 public void disableBackgroundErase(Canvas canvas) { 401 WCanvasPeer peer = (WCanvasPeer)canvas.getPeer(); 402 if (peer == null) { 403 throw new IllegalStateException("Canvas must have a valid peer"); 404 } 405 peer.disableBackgroundErase(); 406 } 407 408 public PanelPeer createPanel(Panel target) { 409 PanelPeer peer = new WPanelPeer(target); 410 targetCreatedPeer(target, peer); 411 return peer; 412 } 413 414 public WindowPeer createWindow(Window target) { 415 WindowPeer peer = new WWindowPeer(target); 416 targetCreatedPeer(target, peer); 417 return peer; 418 } 419 420 public DialogPeer createDialog(Dialog target) { 421 DialogPeer peer = new WDialogPeer(target); 422 targetCreatedPeer(target, peer); 423 return peer; 424 } 425 426 public FileDialogPeer createFileDialog(FileDialog target) { 427 FileDialogPeer peer = new WFileDialogPeer(target); 428 targetCreatedPeer(target, peer); 429 return peer; 430 } 431 432 public MenuBarPeer createMenuBar(MenuBar target) { 433 MenuBarPeer peer = new WMenuBarPeer(target); 434 targetCreatedPeer(target, peer); 435 return peer; 436 } 437 438 public MenuPeer createMenu(Menu target) { 439 MenuPeer peer = new WMenuPeer(target); 440 targetCreatedPeer(target, peer); 441 return peer; 442 } 443 444 public PopupMenuPeer createPopupMenu(PopupMenu target) { 445 PopupMenuPeer peer = new WPopupMenuPeer(target); 446 targetCreatedPeer(target, peer); 447 return peer; 448 } 449 450 public MenuItemPeer createMenuItem(MenuItem target) { 451 MenuItemPeer peer = new WMenuItemPeer(target); 452 targetCreatedPeer(target, peer); 453 return peer; 454 } 455 456 public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) { 457 CheckboxMenuItemPeer peer = new WCheckboxMenuItemPeer(target); 458 targetCreatedPeer(target, peer); 459 return peer; 460 } 461 462 public RobotPeer createRobot(Robot target, GraphicsDevice screen) { 463 // (target is unused for now) 464 // Robot's don't need to go in the peer map since 465 // they're not Component's 466 return new WRobotPeer(screen); 467 } 468 469 public WEmbeddedFramePeer createEmbeddedFrame(WEmbeddedFrame target) { 470 WEmbeddedFramePeer peer = new WEmbeddedFramePeer(target); 471 targetCreatedPeer(target, peer); 472 return peer; 473 } 474 475 WPrintDialogPeer createWPrintDialog(WPrintDialog target) { 476 WPrintDialogPeer peer = new WPrintDialogPeer(target); 477 targetCreatedPeer(target, peer); 478 return peer; 479 } 480 481 WPageDialogPeer createWPageDialog(WPageDialog target) { 482 WPageDialogPeer peer = new WPageDialogPeer(target); 483 targetCreatedPeer(target, peer); 484 return peer; 485 } 486 487 public TrayIconPeer createTrayIcon(TrayIcon target) { 488 WTrayIconPeer peer = new WTrayIconPeer(target); 489 targetCreatedPeer(target, peer); 490 return peer; 491 } 492 493 public SystemTrayPeer createSystemTray(SystemTray target) { 494 return new WSystemTrayPeer(target); 495 } 496 497 public boolean isTraySupported() { 498 return true; 499 } 500 501 public KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager) 502 throws HeadlessException 503 { 504 return new WKeyboardFocusManagerPeer(manager); 505 } 506 507 protected native void setDynamicLayoutNative(boolean b); 508 509 public void setDynamicLayout(boolean b) { 510 if (b == dynamicLayoutSetting) { 511 return; 512 } 513 514 dynamicLayoutSetting = b; 515 setDynamicLayoutNative(b); 516 } 517 518 protected boolean isDynamicLayoutSet() { 519 return dynamicLayoutSetting; 520 } 521 522 /* 523 * Called from lazilyLoadDynamicLayoutSupportedProperty because 524 * Windows doesn't always send WM_SETTINGCHANGE when it should. 525 */ 526 protected native boolean isDynamicLayoutSupportedNative(); 527 528 public boolean isDynamicLayoutActive() { 529 return (isDynamicLayoutSet() && isDynamicLayoutSupported()); 530 } 531 532 /** 533 * Returns <code>true</code> if this frame state is supported. 534 */ 535 public boolean isFrameStateSupported(int state) { 536 switch (state) { 537 case Frame.NORMAL: 538 case Frame.ICONIFIED: 539 case Frame.MAXIMIZED_BOTH: 540 return true; 541 default: 542 return false; 543 } 544 } 545 546 static native ColorModel makeColorModel(); 547 static ColorModel screenmodel; 548 549 static ColorModel getStaticColorModel() { 550 if (GraphicsEnvironment.isHeadless()) { 551 throw new IllegalArgumentException(); 552 } 553 if (config == null) { 554 resetGC(); 555 } 556 return config.getColorModel(); 557 } 558 559 public ColorModel getColorModel() { 560 return getStaticColorModel(); 561 } 562 563 public Insets getScreenInsets(GraphicsConfiguration gc) 564 { 565 return getScreenInsets(((Win32GraphicsDevice) gc.getDevice()).getScreen()); 566 } 567 568 public int getScreenResolution() { 569 Win32GraphicsEnvironment ge = (Win32GraphicsEnvironment) 570 GraphicsEnvironment.getLocalGraphicsEnvironment(); 571 return ge.getXResolution(); 572 } 573 protected native int getScreenWidth(); 574 protected native int getScreenHeight(); 575 protected native Insets getScreenInsets(int screen); 576 577 578 public FontMetrics getFontMetrics(Font font) { 579 // This is an unsupported hack, but left in for a customer. 580 // Do not remove. 581 FontManager fm = FontManagerFactory.getInstance(); 582 if (fm instanceof SunFontManager 583 && ((SunFontManager) fm).usePlatformFontMetrics()) { 584 return WFontMetrics.getFontMetrics(font); 585 } 586 return super.getFontMetrics(font); 587 } 588 589 public FontPeer getFontPeer(String name, int style) { 590 FontPeer retval = null; 591 String lcName = name.toLowerCase(); 592 if (null != cacheFontPeer) { 593 retval = (FontPeer)cacheFontPeer.get(lcName + style); 594 if (null != retval) { 595 return retval; 596 } 597 } 598 retval = new WFontPeer(name, style); 599 if (retval != null) { 600 if (null == cacheFontPeer) { 601 cacheFontPeer = new Hashtable(5, (float)0.9); 602 } 603 if (null != cacheFontPeer) { 604 cacheFontPeer.put(lcName + style, retval); 605 } 606 } 607 return retval; 608 } 609 610 private native void nativeSync(); 611 612 public void sync() { 613 // flush the GDI/DD buffers 614 nativeSync(); 615 // now flush the OGL pipeline (this is a no-op if OGL is not enabled) 616 OGLRenderQueue.sync(); 617 // now flush the D3D pipeline (this is a no-op if D3D is not enabled) 618 D3DRenderQueue.sync(); 619 } 620 621 public PrintJob getPrintJob(Frame frame, String doctitle, 622 Properties props) { 623 return getPrintJob(frame, doctitle, null, null); 624 } 625 626 public PrintJob getPrintJob(Frame frame, String doctitle, 627 JobAttributes jobAttributes, 628 PageAttributes pageAttributes) { 629 630 if (GraphicsEnvironment.isHeadless()) { 631 throw new IllegalArgumentException(); 632 } 633 634 PrintJob2D printJob = new PrintJob2D(frame, doctitle, 635 jobAttributes, pageAttributes); 636 637 if (printJob.printDialog() == false) { 638 printJob = null; 639 } 640 641 return printJob; 642 } 643 644 public native void beep(); 645 646 public boolean getLockingKeyState(int key) { 647 if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK || 648 key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) { 649 throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState"); 650 } 651 return getLockingKeyStateNative(key); 652 } 653 654 public native boolean getLockingKeyStateNative(int key); 655 656 public void setLockingKeyState(int key, boolean on) { 657 if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK || 658 key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) { 659 throw new IllegalArgumentException("invalid key for Toolkit.setLockingKeyState"); 660 } 661 setLockingKeyStateNative(key, on); 662 } 663 664 public native void setLockingKeyStateNative(int key, boolean on); 665 666 public Clipboard getSystemClipboard() { 667 SecurityManager security = System.getSecurityManager(); 668 if (security != null) { 669 security.checkSystemClipboardAccess(); 670 } 671 synchronized (this) { 672 if (clipboard == null) { 673 clipboard = new WClipboard(); 674 } 675 } 676 return clipboard; 677 } 678 679 protected native void loadSystemColors(int[] systemColors); 680 681 public static final Object targetToPeer(Object target) { 682 return SunToolkit.targetToPeer(target); 683 } 684 685 public static final void targetDisposedPeer(Object target, Object peer) { 686 SunToolkit.targetDisposedPeer(target, peer); 687 } 688 689 /** 690 * Returns a new input method adapter descriptor for native input methods. 691 */ 692 public InputMethodDescriptor getInputMethodAdapterDescriptor() { 693 return new WInputMethodDescriptor(); 694 } 695 696 /** 697 * Returns a style map for the input method highlight. 698 */ 699 public Map mapInputMethodHighlight(InputMethodHighlight highlight) { 700 return WInputMethod.mapInputMethodHighlight(highlight); 701 } 702 703 /** 704 * Returns whether enableInputMethods should be set to true for peered 705 * TextComponent instances on this platform. 706 */ 707 public boolean enableInputMethodsForTextComponent() { 708 return true; 709 } 710 711 /** 712 * Returns the default keyboard locale of the underlying operating system 713 */ 714 public Locale getDefaultKeyboardLocale() { 715 Locale locale = WInputMethod.getNativeLocale(); 716 717 if (locale == null) { 718 return super.getDefaultKeyboardLocale(); 719 } else { 720 return locale; 721 } 722 } 723 724 /** 725 * Returns a new custom cursor. 726 */ 727 public Cursor createCustomCursor(Image cursor, Point hotSpot, String name) 728 throws IndexOutOfBoundsException { 729 return new WCustomCursor(cursor, hotSpot, name); 730 } 731 732 /** 733 * Returns the supported cursor size (Win32 only has one). 734 */ 735 public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) { 736 return new Dimension(WCustomCursor.getCursorWidth(), 737 WCustomCursor.getCursorHeight()); 738 } 739 740 public native int getMaximumCursorColors(); 741 742 static void paletteChanged() { 743 ((Win32GraphicsEnvironment)GraphicsEnvironment 744 .getLocalGraphicsEnvironment()) 745 .paletteChanged(); 746 } 747 748 /* 749 * Called from Toolkit native code when a WM_DISPLAYCHANGE occurs. 750 * Have Win32GraphicsEnvironment execute the display change code on the 751 * Event thread. 752 */ 753 static public void displayChanged() { 754 EventQueue.invokeLater(new Runnable() { 755 public void run() { 756 ((Win32GraphicsEnvironment)GraphicsEnvironment 757 .getLocalGraphicsEnvironment()) 758 .displayChanged(); 759 } 760 }); 761 } 762 763 /** 764 * create the peer for a DragSourceContext 765 */ 766 767 public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { 768 return WDragSourceContextPeer.createDragSourceContextPeer(dge); 769 } 770 771 public <T extends DragGestureRecognizer> T 772 createDragGestureRecognizer(Class<T> abstractRecognizerClass, 773 DragSource ds, Component c, int srcActions, 774 DragGestureListener dgl) 775 { 776 if (MouseDragGestureRecognizer.class.equals(abstractRecognizerClass)) 777 return (T)new WMouseDragGestureRecognizer(ds, c, srcActions, dgl); 778 else 779 return null; 780 } 781 782 /** 783 * 784 */ 785 786 private static final String prefix = "DnD.Cursor."; 787 private static final String postfix = ".32x32"; 788 private static final String awtPrefix = "awt."; 789 private static final String dndPrefix = "DnD."; 790 791 protected Object lazilyLoadDesktopProperty(String name) { 792 if (name.startsWith(prefix)) { 793 String cursorName = name.substring(prefix.length(), name.length()) + postfix; 794 795 try { 796 return Cursor.getSystemCustomCursor(cursorName); 797 } catch (AWTException awte) { 798 throw new RuntimeException("cannot load system cursor: " + cursorName, awte); 799 } 800 } 801 802 if (name.equals("awt.dynamicLayoutSupported")) { 803 return Boolean.valueOf(isDynamicLayoutSupported()); 804 } 805 806 if (WDesktopProperties.isWindowsProperty(name) || 807 name.startsWith(awtPrefix) || name.startsWith(dndPrefix)) 808 { 809 synchronized(this) { 810 lazilyInitWProps(); 811 return desktopProperties.get(name); 812 } 813 } 814 815 return super.lazilyLoadDesktopProperty(name); 816 } 817 818 private synchronized void lazilyInitWProps() { 819 if (wprops == null) { 820 wprops = new WDesktopProperties(this); 821 updateProperties(); 822 } 823 } 824 825 /* 826 * Called from lazilyLoadDesktopProperty because Windows doesn't 827 * always send WM_SETTINGCHANGE when it should. 828 */ 829 private synchronized boolean isDynamicLayoutSupported() { 830 boolean nativeDynamic = isDynamicLayoutSupportedNative(); 831 lazilyInitWProps(); 832 Boolean prop = (Boolean) desktopProperties.get("awt.dynamicLayoutSupported"); 833 834 if (log.isLoggable(PlatformLogger.FINER)) { 835 log.finer("In WTK.isDynamicLayoutSupported()" + 836 " nativeDynamic == " + nativeDynamic + 837 " wprops.dynamic == " + prop); 838 } 839 840 if ((prop == null) || (nativeDynamic != prop.booleanValue())) { 841 // We missed the WM_SETTINGCHANGE, so we pretend 842 // we just got one - fire the propertyChange, etc. 843 windowsSettingChange(); 844 return nativeDynamic; 845 } 846 847 return prop.booleanValue(); 848 } 849 850 /* 851 * Called from native toolkit code when WM_SETTINGCHANGE message received 852 * Also called from lazilyLoadDynamicLayoutSupportedProperty because 853 * Windows doesn't always send WM_SETTINGCHANGE when it should. 854 */ 855 private void windowsSettingChange() { 856 EventQueue.invokeLater(new Runnable() { 857 public void run() { 858 updateProperties(); 859 } 860 }); 861 } 862 863 private synchronized void updateProperties() { 864 if (null == wprops) { 865 // wprops has not been initialized, so we have nothing to update 866 return; 867 } 868 869 Map<String, Object> props = wprops.getProperties(); 870 for (String propName : props.keySet()) { 871 Object val = props.get(propName); 872 if (log.isLoggable(PlatformLogger.FINER)) { 873 log.finer("changed " + propName + " to " + val); 874 } 875 setDesktopProperty(propName, val); 876 } 877 } 878 879 public synchronized void addPropertyChangeListener(String name, PropertyChangeListener pcl) { 880 if ( WDesktopProperties.isWindowsProperty(name) 881 || name.startsWith(awtPrefix) 882 || name.startsWith(dndPrefix)) 883 { 884 // someone is interested in Windows-specific desktop properties 885 // we should initialize wprops 886 lazilyInitWProps(); 887 } 888 super.addPropertyChangeListener(name, pcl); 889 } 890 891 /* 892 * initialize only static props here and do not try to initialize props which depends on wprops, 893 * this should be done in lazilyLoadDesktopProperty() only. 894 */ 895 protected synchronized void initializeDesktopProperties() { 896 desktopProperties.put("DnD.Autoscroll.initialDelay", 897 Integer.valueOf(50)); 898 desktopProperties.put("DnD.Autoscroll.interval", 899 Integer.valueOf(50)); 900 desktopProperties.put("DnD.isDragImageSupported", 901 Boolean.TRUE); 902 desktopProperties.put("Shell.shellFolderManager", 903 "sun.awt.shell.Win32ShellFolderManager2"); 904 } 905 906 /* 907 * This returns the value for the desktop property "awt.font.desktophints" 908 * This requires that the Windows properties have already been gathered. 909 */ 910 protected synchronized RenderingHints getDesktopAAHints() { 911 if (wprops == null) { 912 return null; 913 } else { 914 return wprops.getDesktopAAHints(); 915 } 916 } 917 918 public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) { 919 return (modalityType == null) || 920 (modalityType == Dialog.ModalityType.MODELESS) || 921 (modalityType == Dialog.ModalityType.DOCUMENT_MODAL) || 922 (modalityType == Dialog.ModalityType.APPLICATION_MODAL) || 923 (modalityType == Dialog.ModalityType.TOOLKIT_MODAL); 924 } 925 926 public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) { 927 return (exclusionType == null) || 928 (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE) || 929 (exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) || 930 (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE); 931 } 932 933 public static WToolkit getWToolkit() { 934 WToolkit toolkit = (WToolkit)Toolkit.getDefaultToolkit(); 935 return toolkit; 936 } 937 938 /** 939 * There are two reasons why we don't use buffer per window when 940 * Vista's DWM (aka Aero) is enabled: 941 * - since with DWM all windows are already double-buffered, the application 942 * doesn't get expose events so we don't get to use our true back-buffer, 943 * wasting memory and performance (this is valid for both d3d and gdi 944 * pipelines) 945 * - in some cases with buffer per window enabled it is possible for the 946 * paint manager to redirect rendering to the screen for some operations 947 * (like copyArea), and since bpw uses its own BufferStrategy the 948 * d3d onscreen rendering support is disabled and rendering goes through 949 * GDI. This doesn't work well with Vista's DWM since one 950 * can not perform GDI and D3D operations on the same surface 951 * (see 6630702 for more info) 952 * 953 * Note: even though DWM composition state can change during the lifetime 954 * of the application it is a rare event, and it is more often that it 955 * is temporarily disabled (because of some app) than it is getting 956 * permanently enabled so we can live with this approach without the 957 * complexity of dwm state listeners and such. This can be revisited if 958 * proved otherwise. 959 */ 960 @Override 961 public boolean useBufferPerWindow() { 962 return !Win32GraphicsEnvironment.isDWMCompositionEnabled(); 963 } 964 965 public void grab(Window w) { 966 if (w.getPeer() != null) { 967 ((WWindowPeer)w.getPeer()).grab(); 968 } 969 } 970 971 public void ungrab(Window w) { 972 if (w.getPeer() != null) { 973 ((WWindowPeer)w.getPeer()).ungrab(); 974 } 975 } 976 977 public native boolean syncNativeQueue(final long timeout); 978 public boolean isDesktopSupported() { 979 return true; 980 } 981 982 public DesktopPeer createDesktopPeer(Desktop target) { 983 return new WDesktopPeer(); 984 } 985 986 public static native void setExtraMouseButtonsEnabledNative(boolean enable); 987 988 public boolean areExtraMouseButtonsEnabled() throws HeadlessException { 989 return areExtraMouseButtonsEnabled; 990 } 991 992 private native synchronized int getNumberOfButtonsImpl(); 993 994 @Override 995 public int getNumberOfButtons(){ 996 if (numberOfButtons == 0) { 997 numberOfButtons = getNumberOfButtonsImpl(); 998 } 999 return (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons; 1000 } 1001 1002 @Override 1003 public boolean isWindowOpacitySupported() { 1004 // supported in Win2K and later 1005 return true; 1006 } 1007 1008 @Override 1009 public boolean isWindowShapingSupported() { 1010 return true; 1011 } 1012 1013 @Override 1014 public boolean isWindowTranslucencySupported() { 1015 // supported in Win2K and later 1016 return true; 1017 } 1018 1019 @Override 1020 public boolean isTranslucencyCapable(GraphicsConfiguration gc) { 1021 //XXX: worth checking if 8-bit? Anyway, it doesn't hurt. 1022 return true; 1023 } 1024 1025 // On MS Windows one must use the peer.updateWindow() to implement 1026 // non-opaque windows. 1027 @Override 1028 public boolean needUpdateWindow() { 1029 return true; 1030 } 1031 }