| /* |
| * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.awt.windows; |
| |
| import java.awt.*; |
| import java.awt.im.InputMethodHighlight; |
| import java.awt.im.spi.InputMethodDescriptor; |
| import java.awt.image.*; |
| import java.awt.peer.*; |
| import java.awt.event.KeyEvent; |
| import java.awt.datatransfer.Clipboard; |
| import java.awt.TrayIcon; |
| import java.beans.PropertyChangeListener; |
| import java.security.AccessController; |
| import java.security.PrivilegedAction; |
| import sun.awt.AWTAutoShutdown; |
| import sun.awt.AWTPermissions; |
| import sun.awt.LightweightFrame; |
| import sun.awt.SunToolkit; |
| import sun.awt.Win32GraphicsDevice; |
| import sun.awt.Win32GraphicsEnvironment; |
| import sun.java2d.d3d.D3DRenderQueue; |
| import sun.java2d.opengl.OGLRenderQueue; |
| |
| import sun.print.PrintJob2D; |
| |
| import java.awt.dnd.DragSource; |
| import java.awt.dnd.DragGestureListener; |
| import java.awt.dnd.DragGestureEvent; |
| import java.awt.dnd.DragGestureRecognizer; |
| import java.awt.dnd.MouseDragGestureRecognizer; |
| import java.awt.dnd.InvalidDnDOperationException; |
| import java.awt.dnd.peer.DragSourceContextPeer; |
| |
| import java.util.Hashtable; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Properties; |
| |
| import sun.font.FontManager; |
| import sun.font.FontManagerFactory; |
| import sun.font.SunFontManager; |
| import sun.misc.PerformanceLogger; |
| import sun.util.logging.PlatformLogger; |
| |
| public class WToolkit extends SunToolkit implements Runnable { |
| |
| private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WToolkit"); |
| |
| static GraphicsConfiguration config; |
| |
| // System clipboard. |
| WClipboard clipboard; |
| |
| // cache of font peers |
| private Hashtable<String,FontPeer> cacheFontPeer; |
| |
| // Windows properties |
| private WDesktopProperties wprops; |
| |
| // Dynamic Layout Resize client code setting |
| protected boolean dynamicLayoutSetting = false; |
| |
| //Is it allowed to generate events assigned to extra mouse buttons. |
| //Set to true by default. |
| private static boolean areExtraMouseButtonsEnabled = true; |
| |
| /** |
| * Initialize JNI field and method IDs |
| */ |
| private static native void initIDs(); |
| private static boolean loaded = false; |
| public static void loadLibraries() { |
| if (!loaded) { |
| java.security.AccessController.doPrivileged( |
| new java.security.PrivilegedAction<Void>() { |
| public Void run() { |
| System.loadLibrary("awt"); |
| return null; |
| } |
| }); |
| loaded = true; |
| } |
| } |
| |
| private static native String getWindowsVersion(); |
| |
| static { |
| loadLibraries(); |
| initIDs(); |
| |
| // Print out which version of Windows is running |
| if (log.isLoggable(PlatformLogger.Level.FINE)) { |
| log.fine("Win version: " + getWindowsVersion()); |
| } |
| |
| AccessController.doPrivileged( |
| new PrivilegedAction <Void> () |
| { |
| public Void run() { |
| String browserProp = System.getProperty("browser"); |
| if (browserProp != null && browserProp.equals("sun.plugin")) { |
| disableCustomPalette(); |
| } |
| return null; |
| } |
| }); |
| } |
| |
| private static native void disableCustomPalette(); |
| |
| /* |
| * Reset the static GraphicsConfiguration to the default. Called on |
| * startup and when display settings have changed. |
| */ |
| public static void resetGC() { |
| if (GraphicsEnvironment.isHeadless()) { |
| config = null; |
| } else { |
| config = (GraphicsEnvironment |
| .getLocalGraphicsEnvironment() |
| .getDefaultScreenDevice() |
| .getDefaultConfiguration()); |
| } |
| } |
| |
| /* |
| * NOTE: The following embedded*() methods are non-public API intended |
| * for internal use only. The methods are unsupported and could go |
| * away in future releases. |
| * |
| * New hook functions for using the AWT as an embedded service. These |
| * functions replace the global C function AwtInit() which was previously |
| * exported by awt.dll. |
| * |
| * When used as an embedded service, the AWT does NOT have its own |
| * message pump. It instead relies on the parent application to provide |
| * this functionality. embeddedInit() assumes that the thread on which it |
| * is called is the message pumping thread. Violating this assumption |
| * will lead to undefined behavior. |
| * |
| * embeddedInit must be called before the WToolkit() constructor. |
| * embeddedDispose should be called before the applicaton terminates the |
| * Java VM. It is currently unsafe to reinitialize the toolkit again |
| * after it has been disposed. Instead, awt.dll must be reloaded and the |
| * class loader which loaded WToolkit must be finalized before it is |
| * safe to reuse AWT. Dynamic reusability may be added to the toolkit in |
| * the future. |
| */ |
| |
| /** |
| * Initializes the Toolkit for use in an embedded environment. |
| * |
| * @return true if the the initialization succeeded; false if it failed. |
| * The function will fail if the Toolkit was already initialized. |
| * @since 1.3 |
| */ |
| public static native boolean embeddedInit(); |
| |
| /** |
| * Disposes the Toolkit in an embedded environment. This method should |
| * not be called on exit unless the Toolkit was constructed with |
| * embeddedInit. |
| * |
| * @return true if the disposal succeeded; false if it failed. The |
| * function will fail if the calling thread is not the same |
| * thread which called embeddedInit(), or if the Toolkit was |
| * already disposed. |
| * @since 1.3 |
| */ |
| public static native boolean embeddedDispose(); |
| |
| /** |
| * To be called after processing the event queue by users of the above |
| * embeddedInit() function. The reason for this additional call is that |
| * there are some operations performed during idle time in the AwtToolkit |
| * event loop which should also be performed during idle time in any |
| * other native event loop. Failure to do so could result in |
| * deadlocks. |
| * |
| * This method was added at the last minute of the jdk1.4 release |
| * to work around a specific customer problem. As with the above |
| * embedded*() class, this method is non-public and should not be |
| * used by external applications. |
| * |
| * See bug #4526587 for more information. |
| */ |
| public native void embeddedEventLoopIdleProcessing(); |
| |
| public static final String DATA_TRANSFERER_CLASS_NAME = "sun.awt.windows.WDataTransferer"; |
| |
| static class ToolkitDisposer implements sun.java2d.DisposerRecord { |
| public void dispose() { |
| WToolkit.postDispose(); |
| } |
| } |
| |
| private final Object anchor = new Object(); |
| |
| private static native void postDispose(); |
| |
| private static native boolean startToolkitThread(Runnable thread); |
| |
| public WToolkit() { |
| // Startup toolkit threads |
| if (PerformanceLogger.loggingEnabled()) { |
| PerformanceLogger.setTime("WToolkit construction"); |
| } |
| |
| sun.java2d.Disposer.addRecord(anchor, new ToolkitDisposer()); |
| |
| /* |
| * Fix for 4701990. |
| * AWTAutoShutdown state must be changed before the toolkit thread |
| * starts to avoid race condition. |
| */ |
| AWTAutoShutdown.notifyToolkitThreadBusy(); |
| |
| if (!startToolkitThread(this)) { |
| Thread toolkitThread = new Thread(this, "AWT-Windows"); |
| toolkitThread.setDaemon(true); |
| toolkitThread.start(); |
| } |
| |
| try { |
| synchronized(this) { |
| while(!inited) { |
| wait(); |
| } |
| } |
| } catch (InterruptedException x) { |
| // swallow the exception |
| } |
| |
| SunToolkit.setDataTransfererClassName(DATA_TRANSFERER_CLASS_NAME); |
| |
| // Enabled "live resizing" by default. It remains controlled |
| // by the native system though. |
| setDynamicLayout(true); |
| |
| areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons", "true")); |
| //set system property if not yet assigned |
| System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled); |
| setExtraMouseButtonsEnabledNative(areExtraMouseButtonsEnabled); |
| } |
| |
| private final void registerShutdownHook() { |
| AccessController.doPrivileged(new PrivilegedAction<Void>() { |
| public Void run() { |
| ThreadGroup currentTG = |
| Thread.currentThread().getThreadGroup(); |
| ThreadGroup parentTG = currentTG.getParent(); |
| while (parentTG != null) { |
| currentTG = parentTG; |
| parentTG = currentTG.getParent(); |
| } |
| Thread shutdown = new Thread(currentTG, new Runnable() { |
| public void run() { |
| shutdown(); |
| } |
| }); |
| shutdown.setContextClassLoader(null); |
| Runtime.getRuntime().addShutdownHook(shutdown); |
| return null; |
| } |
| }); |
| } |
| |
| public void run() { |
| Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1); |
| boolean startPump = init(); |
| |
| if (startPump) { |
| registerShutdownHook(); |
| } |
| |
| synchronized(this) { |
| inited = true; |
| notifyAll(); |
| } |
| |
| if (startPump) { |
| eventLoop(); // will Dispose Toolkit when shutdown hook executes |
| } |
| } |
| |
| /* |
| * eventLoop() begins the native message pump which retrieves and processes |
| * native events. |
| * |
| * When shutdown() is called by the ShutdownHook added in run(), a |
| * WM_QUIT message is posted to the Toolkit thread indicating that |
| * eventLoop() should Dispose the toolkit and exit. |
| */ |
| private native boolean init(); |
| private boolean inited = false; |
| |
| private native void eventLoop(); |
| private native void shutdown(); |
| |
| /* |
| * Instead of blocking the "AWT-Windows" thread uselessly on a semaphore, |
| * use these functions. startSecondaryEventLoop() corresponds to wait() |
| * and quitSecondaryEventLoop() corresponds to notify. |
| * |
| * These functions simulate blocking while allowing the AWT to continue |
| * processing native events, eliminating a potential deadlock situation |
| * with SendMessage. |
| * |
| * WARNING: startSecondaryEventLoop must only be called from the "AWT- |
| * Windows" thread. |
| */ |
| public static native void startSecondaryEventLoop(); |
| public static native void quitSecondaryEventLoop(); |
| |
| /* |
| * Create peer objects. |
| */ |
| |
| public ButtonPeer createButton(Button target) { |
| ButtonPeer peer = new WButtonPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public TextFieldPeer createTextField(TextField target) { |
| TextFieldPeer peer = new WTextFieldPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public LabelPeer createLabel(Label target) { |
| LabelPeer peer = new WLabelPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public ListPeer createList(List target) { |
| ListPeer peer = new WListPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public CheckboxPeer createCheckbox(Checkbox target) { |
| CheckboxPeer peer = new WCheckboxPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public ScrollbarPeer createScrollbar(Scrollbar target) { |
| ScrollbarPeer peer = new WScrollbarPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public ScrollPanePeer createScrollPane(ScrollPane target) { |
| ScrollPanePeer peer = new WScrollPanePeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public TextAreaPeer createTextArea(TextArea target) { |
| TextAreaPeer peer = new WTextAreaPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public ChoicePeer createChoice(Choice target) { |
| ChoicePeer peer = new WChoicePeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public FramePeer createFrame(Frame target) { |
| FramePeer peer = new WFramePeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public FramePeer createLightweightFrame(LightweightFrame target) { |
| FramePeer peer = new WLightweightFramePeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public CanvasPeer createCanvas(Canvas target) { |
| CanvasPeer peer = new WCanvasPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| @SuppressWarnings("deprecation") |
| public void disableBackgroundErase(Canvas canvas) { |
| WCanvasPeer peer = (WCanvasPeer)canvas.getPeer(); |
| if (peer == null) { |
| throw new IllegalStateException("Canvas must have a valid peer"); |
| } |
| peer.disableBackgroundErase(); |
| } |
| |
| public PanelPeer createPanel(Panel target) { |
| PanelPeer peer = new WPanelPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public WindowPeer createWindow(Window target) { |
| WindowPeer peer = new WWindowPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public DialogPeer createDialog(Dialog target) { |
| DialogPeer peer = new WDialogPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public FileDialogPeer createFileDialog(FileDialog target) { |
| FileDialogPeer peer = new WFileDialogPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public MenuBarPeer createMenuBar(MenuBar target) { |
| MenuBarPeer peer = new WMenuBarPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public MenuPeer createMenu(Menu target) { |
| MenuPeer peer = new WMenuPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public PopupMenuPeer createPopupMenu(PopupMenu target) { |
| PopupMenuPeer peer = new WPopupMenuPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public MenuItemPeer createMenuItem(MenuItem target) { |
| MenuItemPeer peer = new WMenuItemPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target) { |
| CheckboxMenuItemPeer peer = new WCheckboxMenuItemPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public RobotPeer createRobot(Robot target, GraphicsDevice screen) { |
| // (target is unused for now) |
| // Robot's don't need to go in the peer map since |
| // they're not Component's |
| return new WRobotPeer(screen); |
| } |
| |
| public WEmbeddedFramePeer createEmbeddedFrame(WEmbeddedFrame target) { |
| WEmbeddedFramePeer peer = new WEmbeddedFramePeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| WPrintDialogPeer createWPrintDialog(WPrintDialog target) { |
| WPrintDialogPeer peer = new WPrintDialogPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| WPageDialogPeer createWPageDialog(WPageDialog target) { |
| WPageDialogPeer peer = new WPageDialogPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public TrayIconPeer createTrayIcon(TrayIcon target) { |
| WTrayIconPeer peer = new WTrayIconPeer(target); |
| targetCreatedPeer(target, peer); |
| return peer; |
| } |
| |
| public SystemTrayPeer createSystemTray(SystemTray target) { |
| return new WSystemTrayPeer(target); |
| } |
| |
| public boolean isTraySupported() { |
| return true; |
| } |
| |
| public KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() |
| throws HeadlessException |
| { |
| return WKeyboardFocusManagerPeer.getInstance(); |
| } |
| |
| protected native void setDynamicLayoutNative(boolean b); |
| |
| public void setDynamicLayout(boolean b) { |
| if (b == dynamicLayoutSetting) { |
| return; |
| } |
| |
| dynamicLayoutSetting = b; |
| setDynamicLayoutNative(b); |
| } |
| |
| protected boolean isDynamicLayoutSet() { |
| return dynamicLayoutSetting; |
| } |
| |
| /* |
| * Called from lazilyLoadDynamicLayoutSupportedProperty because |
| * Windows doesn't always send WM_SETTINGCHANGE when it should. |
| */ |
| protected native boolean isDynamicLayoutSupportedNative(); |
| |
| public boolean isDynamicLayoutActive() { |
| return (isDynamicLayoutSet() && isDynamicLayoutSupported()); |
| } |
| |
| /** |
| * Returns <code>true</code> if this frame state is supported. |
| */ |
| public boolean isFrameStateSupported(int state) { |
| switch (state) { |
| case Frame.NORMAL: |
| case Frame.ICONIFIED: |
| case Frame.MAXIMIZED_BOTH: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| static native ColorModel makeColorModel(); |
| static ColorModel screenmodel; |
| |
| static ColorModel getStaticColorModel() { |
| if (GraphicsEnvironment.isHeadless()) { |
| throw new IllegalArgumentException(); |
| } |
| if (config == null) { |
| resetGC(); |
| } |
| return config.getColorModel(); |
| } |
| |
| public ColorModel getColorModel() { |
| return getStaticColorModel(); |
| } |
| |
| public Insets getScreenInsets(GraphicsConfiguration gc) |
| { |
| return getScreenInsets(((Win32GraphicsDevice) gc.getDevice()).getScreen()); |
| } |
| |
| public int getScreenResolution() { |
| Win32GraphicsEnvironment ge = (Win32GraphicsEnvironment) |
| GraphicsEnvironment.getLocalGraphicsEnvironment(); |
| return ge.getXResolution(); |
| } |
| protected native int getScreenWidth(); |
| protected native int getScreenHeight(); |
| protected native Insets getScreenInsets(int screen); |
| |
| |
| public FontMetrics getFontMetrics(Font font) { |
| // This is an unsupported hack, but left in for a customer. |
| // Do not remove. |
| FontManager fm = FontManagerFactory.getInstance(); |
| if (fm instanceof SunFontManager |
| && ((SunFontManager) fm).usePlatformFontMetrics()) { |
| return WFontMetrics.getFontMetrics(font); |
| } |
| return super.getFontMetrics(font); |
| } |
| |
| public FontPeer getFontPeer(String name, int style) { |
| FontPeer retval = null; |
| String lcName = name.toLowerCase(); |
| if (null != cacheFontPeer) { |
| retval = cacheFontPeer.get(lcName + style); |
| if (null != retval) { |
| return retval; |
| } |
| } |
| retval = new WFontPeer(name, style); |
| if (retval != null) { |
| if (null == cacheFontPeer) { |
| cacheFontPeer = new Hashtable<>(5, 0.9f); |
| } |
| if (null != cacheFontPeer) { |
| cacheFontPeer.put(lcName + style, retval); |
| } |
| } |
| return retval; |
| } |
| |
| private native void nativeSync(); |
| |
| public void sync() { |
| // flush the GDI/DD buffers |
| nativeSync(); |
| // now flush the OGL pipeline (this is a no-op if OGL is not enabled) |
| OGLRenderQueue.sync(); |
| // now flush the D3D pipeline (this is a no-op if D3D is not enabled) |
| D3DRenderQueue.sync(); |
| } |
| |
| public PrintJob getPrintJob(Frame frame, String doctitle, |
| Properties props) { |
| return getPrintJob(frame, doctitle, null, null); |
| } |
| |
| public PrintJob getPrintJob(Frame frame, String doctitle, |
| JobAttributes jobAttributes, |
| PageAttributes pageAttributes) |
| { |
| if (frame == null) { |
| throw new NullPointerException("frame must not be null"); |
| } |
| |
| PrintJob2D printJob = new PrintJob2D(frame, doctitle, |
| jobAttributes, pageAttributes); |
| |
| if (printJob.printDialog() == false) { |
| printJob = null; |
| } |
| |
| return printJob; |
| } |
| |
| public native void beep(); |
| |
| public boolean getLockingKeyState(int key) { |
| if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK || |
| key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) { |
| throw new IllegalArgumentException("invalid key for Toolkit.getLockingKeyState"); |
| } |
| return getLockingKeyStateNative(key); |
| } |
| |
| public native boolean getLockingKeyStateNative(int key); |
| |
| public void setLockingKeyState(int key, boolean on) { |
| if (! (key == KeyEvent.VK_CAPS_LOCK || key == KeyEvent.VK_NUM_LOCK || |
| key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) { |
| throw new IllegalArgumentException("invalid key for Toolkit.setLockingKeyState"); |
| } |
| setLockingKeyStateNative(key, on); |
| } |
| |
| public native void setLockingKeyStateNative(int key, boolean on); |
| |
| public Clipboard getSystemClipboard() { |
| SecurityManager security = System.getSecurityManager(); |
| if (security != null) { |
| security.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION); |
| } |
| synchronized (this) { |
| if (clipboard == null) { |
| clipboard = new WClipboard(); |
| } |
| } |
| return clipboard; |
| } |
| |
| protected native void loadSystemColors(int[] systemColors); |
| |
| public static final Object targetToPeer(Object target) { |
| return SunToolkit.targetToPeer(target); |
| } |
| |
| public static final void targetDisposedPeer(Object target, Object peer) { |
| SunToolkit.targetDisposedPeer(target, peer); |
| } |
| |
| /** |
| * Returns a new input method adapter descriptor for native input methods. |
| */ |
| public InputMethodDescriptor getInputMethodAdapterDescriptor() { |
| return new WInputMethodDescriptor(); |
| } |
| |
| /** |
| * Returns a style map for the input method highlight. |
| */ |
| public Map<java.awt.font.TextAttribute,?> mapInputMethodHighlight( |
| InputMethodHighlight highlight) |
| { |
| return WInputMethod.mapInputMethodHighlight(highlight); |
| } |
| |
| /** |
| * Returns whether enableInputMethods should be set to true for peered |
| * TextComponent instances on this platform. |
| */ |
| public boolean enableInputMethodsForTextComponent() { |
| return true; |
| } |
| |
| /** |
| * Returns the default keyboard locale of the underlying operating system |
| */ |
| public Locale getDefaultKeyboardLocale() { |
| Locale locale = WInputMethod.getNativeLocale(); |
| |
| if (locale == null) { |
| return super.getDefaultKeyboardLocale(); |
| } else { |
| return locale; |
| } |
| } |
| |
| /** |
| * Returns a new custom cursor. |
| */ |
| public Cursor createCustomCursor(Image cursor, Point hotSpot, String name) |
| throws IndexOutOfBoundsException { |
| return new WCustomCursor(cursor, hotSpot, name); |
| } |
| |
| /** |
| * Returns the supported cursor size (Win32 only has one). |
| */ |
| public Dimension getBestCursorSize(int preferredWidth, int preferredHeight) { |
| return new Dimension(WCustomCursor.getCursorWidth(), |
| WCustomCursor.getCursorHeight()); |
| } |
| |
| public native int getMaximumCursorColors(); |
| |
| static void paletteChanged() { |
| ((Win32GraphicsEnvironment)GraphicsEnvironment |
| .getLocalGraphicsEnvironment()) |
| .paletteChanged(); |
| } |
| |
| /* |
| * Called from Toolkit native code when a WM_DISPLAYCHANGE occurs. |
| * Have Win32GraphicsEnvironment execute the display change code on the |
| * Event thread. |
| */ |
| static public void displayChanged() { |
| EventQueue.invokeLater(new Runnable() { |
| public void run() { |
| ((Win32GraphicsEnvironment)GraphicsEnvironment |
| .getLocalGraphicsEnvironment()) |
| .displayChanged(); |
| } |
| }); |
| } |
| |
| /** |
| * create the peer for a DragSourceContext |
| */ |
| |
| public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException { |
| return WDragSourceContextPeer.createDragSourceContextPeer(dge); |
| } |
| |
| public <T extends DragGestureRecognizer> T |
| createDragGestureRecognizer(Class<T> abstractRecognizerClass, |
| DragSource ds, Component c, int srcActions, |
| DragGestureListener dgl) |
| { |
| if (MouseDragGestureRecognizer.class.equals(abstractRecognizerClass)) |
| return (T)new WMouseDragGestureRecognizer(ds, c, srcActions, dgl); |
| else |
| return null; |
| } |
| |
| /** |
| * |
| */ |
| |
| private static final String prefix = "DnD.Cursor."; |
| private static final String postfix = ".32x32"; |
| private static final String awtPrefix = "awt."; |
| private static final String dndPrefix = "DnD."; |
| |
| protected Object lazilyLoadDesktopProperty(String name) { |
| if (name.startsWith(prefix)) { |
| String cursorName = name.substring(prefix.length(), name.length()) + postfix; |
| |
| try { |
| return Cursor.getSystemCustomCursor(cursorName); |
| } catch (AWTException awte) { |
| throw new RuntimeException("cannot load system cursor: " + cursorName, awte); |
| } |
| } |
| |
| if (name.equals("awt.dynamicLayoutSupported")) { |
| return Boolean.valueOf(isDynamicLayoutSupported()); |
| } |
| |
| if (WDesktopProperties.isWindowsProperty(name) || |
| name.startsWith(awtPrefix) || name.startsWith(dndPrefix)) |
| { |
| synchronized(this) { |
| lazilyInitWProps(); |
| return desktopProperties.get(name); |
| } |
| } |
| |
| return super.lazilyLoadDesktopProperty(name); |
| } |
| |
| private synchronized void lazilyInitWProps() { |
| if (wprops == null) { |
| wprops = new WDesktopProperties(this); |
| updateProperties(); |
| } |
| } |
| |
| /* |
| * Called from lazilyLoadDesktopProperty because Windows doesn't |
| * always send WM_SETTINGCHANGE when it should. |
| */ |
| private synchronized boolean isDynamicLayoutSupported() { |
| boolean nativeDynamic = isDynamicLayoutSupportedNative(); |
| lazilyInitWProps(); |
| Boolean prop = (Boolean) desktopProperties.get("awt.dynamicLayoutSupported"); |
| |
| if (log.isLoggable(PlatformLogger.Level.FINER)) { |
| log.finer("In WTK.isDynamicLayoutSupported()" + |
| " nativeDynamic == " + nativeDynamic + |
| " wprops.dynamic == " + prop); |
| } |
| |
| if ((prop == null) || (nativeDynamic != prop.booleanValue())) { |
| // We missed the WM_SETTINGCHANGE, so we pretend |
| // we just got one - fire the propertyChange, etc. |
| windowsSettingChange(); |
| return nativeDynamic; |
| } |
| |
| return prop.booleanValue(); |
| } |
| |
| /* |
| * Called from native toolkit code when WM_SETTINGCHANGE message received |
| * Also called from lazilyLoadDynamicLayoutSupportedProperty because |
| * Windows doesn't always send WM_SETTINGCHANGE when it should. |
| */ |
| private void windowsSettingChange() { |
| EventQueue.invokeLater(new Runnable() { |
| public void run() { |
| updateProperties(); |
| } |
| }); |
| } |
| |
| private synchronized void updateProperties() { |
| if (null == wprops) { |
| // wprops has not been initialized, so we have nothing to update |
| return; |
| } |
| |
| Map<String, Object> props = wprops.getProperties(); |
| for (String propName : props.keySet()) { |
| Object val = props.get(propName); |
| if (log.isLoggable(PlatformLogger.Level.FINER)) { |
| log.finer("changed " + propName + " to " + val); |
| } |
| setDesktopProperty(propName, val); |
| } |
| } |
| |
| public synchronized void addPropertyChangeListener(String name, PropertyChangeListener pcl) { |
| if (name == null) { |
| // See JavaDoc for the Toolkit.addPropertyChangeListener() method |
| return; |
| } |
| if ( WDesktopProperties.isWindowsProperty(name) |
| || name.startsWith(awtPrefix) |
| || name.startsWith(dndPrefix)) |
| { |
| // someone is interested in Windows-specific desktop properties |
| // we should initialize wprops |
| lazilyInitWProps(); |
| } |
| super.addPropertyChangeListener(name, pcl); |
| } |
| |
| /* |
| * initialize only static props here and do not try to initialize props which depends on wprops, |
| * this should be done in lazilyLoadDesktopProperty() only. |
| */ |
| protected synchronized void initializeDesktopProperties() { |
| desktopProperties.put("DnD.Autoscroll.initialDelay", |
| Integer.valueOf(50)); |
| desktopProperties.put("DnD.Autoscroll.interval", |
| Integer.valueOf(50)); |
| desktopProperties.put("DnD.isDragImageSupported", |
| Boolean.TRUE); |
| desktopProperties.put("Shell.shellFolderManager", |
| "sun.awt.shell.Win32ShellFolderManager2"); |
| } |
| |
| /* |
| * This returns the value for the desktop property "awt.font.desktophints" |
| * This requires that the Windows properties have already been gathered. |
| */ |
| protected synchronized RenderingHints getDesktopAAHints() { |
| if (wprops == null) { |
| return null; |
| } else { |
| return wprops.getDesktopAAHints(); |
| } |
| } |
| |
| public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) { |
| return (modalityType == null) || |
| (modalityType == Dialog.ModalityType.MODELESS) || |
| (modalityType == Dialog.ModalityType.DOCUMENT_MODAL) || |
| (modalityType == Dialog.ModalityType.APPLICATION_MODAL) || |
| (modalityType == Dialog.ModalityType.TOOLKIT_MODAL); |
| } |
| |
| public boolean isModalExclusionTypeSupported(Dialog.ModalExclusionType exclusionType) { |
| return (exclusionType == null) || |
| (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE) || |
| (exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE) || |
| (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE); |
| } |
| |
| public static WToolkit getWToolkit() { |
| WToolkit toolkit = (WToolkit)Toolkit.getDefaultToolkit(); |
| return toolkit; |
| } |
| |
| /** |
| * There are two reasons why we don't use buffer per window when |
| * Vista's DWM (aka Aero) is enabled: |
| * - since with DWM all windows are already double-buffered, the application |
| * doesn't get expose events so we don't get to use our true back-buffer, |
| * wasting memory and performance (this is valid for both d3d and gdi |
| * pipelines) |
| * - in some cases with buffer per window enabled it is possible for the |
| * paint manager to redirect rendering to the screen for some operations |
| * (like copyArea), and since bpw uses its own BufferStrategy the |
| * d3d onscreen rendering support is disabled and rendering goes through |
| * GDI. This doesn't work well with Vista's DWM since one |
| * can not perform GDI and D3D operations on the same surface |
| * (see 6630702 for more info) |
| * |
| * Note: even though DWM composition state can change during the lifetime |
| * of the application it is a rare event, and it is more often that it |
| * is temporarily disabled (because of some app) than it is getting |
| * permanently enabled so we can live with this approach without the |
| * complexity of dwm state listeners and such. This can be revisited if |
| * proved otherwise. |
| */ |
| @Override |
| public boolean useBufferPerWindow() { |
| return !Win32GraphicsEnvironment.isDWMCompositionEnabled(); |
| } |
| |
| @SuppressWarnings("deprecation") |
| public void grab(Window w) { |
| if (w.getPeer() != null) { |
| ((WWindowPeer)w.getPeer()).grab(); |
| } |
| } |
| |
| @SuppressWarnings("deprecation") |
| public void ungrab(Window w) { |
| if (w.getPeer() != null) { |
| ((WWindowPeer)w.getPeer()).ungrab(); |
| } |
| } |
| |
| public native boolean syncNativeQueue(final long timeout); |
| public boolean isDesktopSupported() { |
| return true; |
| } |
| |
| public DesktopPeer createDesktopPeer(Desktop target) { |
| return new WDesktopPeer(); |
| } |
| |
| public static native void setExtraMouseButtonsEnabledNative(boolean enable); |
| |
| public boolean areExtraMouseButtonsEnabled() throws HeadlessException { |
| return areExtraMouseButtonsEnabled; |
| } |
| |
| private native synchronized int getNumberOfButtonsImpl(); |
| |
| @Override |
| public int getNumberOfButtons(){ |
| if (numberOfButtons == 0) { |
| numberOfButtons = getNumberOfButtonsImpl(); |
| } |
| return (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons; |
| } |
| |
| @Override |
| public boolean isWindowOpacitySupported() { |
| // supported in Win2K and later |
| return true; |
| } |
| |
| @Override |
| public boolean isWindowShapingSupported() { |
| return true; |
| } |
| |
| @Override |
| public boolean isWindowTranslucencySupported() { |
| // supported in Win2K and later |
| return true; |
| } |
| |
| @Override |
| public boolean isTranslucencyCapable(GraphicsConfiguration gc) { |
| //XXX: worth checking if 8-bit? Anyway, it doesn't hurt. |
| return true; |
| } |
| |
| // On MS Windows one must use the peer.updateWindow() to implement |
| // non-opaque windows. |
| @Override |
| public boolean needUpdateWindow() { |
| return true; |
| } |
| } |