001: /*
002: * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.windows;
027:
028: import java.awt.*;
029: import java.awt.im.InputMethodHighlight;
030: import java.awt.im.spi.InputMethodDescriptor;
031: import java.awt.image.*;
032: import java.awt.peer.*;
033: import java.awt.event.KeyEvent;
034: import java.awt.datatransfer.Clipboard;
035: import java.awt.TrayIcon;
036: import java.util.Hashtable;
037: import java.util.Locale;
038: import java.util.Map;
039: import java.util.Properties;
040: import java.beans.PropertyChangeListener;
041: import java.security.AccessController;
042: import java.security.PrivilegedAction;
043: import java.util.logging.Level;
044: import java.util.logging.Logger;
045: import sun.awt.AWTAutoShutdown;
046: import sun.awt.SunToolkit;
047: import sun.awt.Win32GraphicsDevice;
048: import sun.awt.Win32GraphicsEnvironment;
049: import sun.awt.DebugHelper;
050: import sun.java2d.opengl.OGLRenderQueue;
051:
052: import sun.print.PrintJob2D;
053:
054: import java.awt.dnd.DragSource;
055: import java.awt.dnd.DragGestureListener;
056: import java.awt.dnd.DragGestureEvent;
057: import java.awt.dnd.DragGestureRecognizer;
058: import java.awt.dnd.MouseDragGestureRecognizer;
059: import java.awt.dnd.InvalidDnDOperationException;
060: import java.awt.dnd.peer.DragSourceContextPeer;
061:
062: import sun.misc.PerformanceLogger;
063:
064: public class WToolkit extends SunToolkit implements Runnable {
065: private static final Logger log = Logger
066: .getLogger("sun.awt.windows.WToolkit");
067: private static final DebugHelper dbg = DebugHelper
068: .create(WToolkit.class);
069:
070: static GraphicsConfiguration config;
071:
072: // System clipboard.
073: WClipboard clipboard;
074:
075: // cache of font peers
076: private Hashtable cacheFontPeer;
077:
078: // Windows properties
079: private WDesktopProperties wprops;
080:
081: // Dynamic Layout Resize client code setting
082: protected boolean dynamicLayoutSetting = false;
083:
084: /**
085: * Initialize JNI field and method IDs
086: */
087: private static native void initIDs();
088:
089: private static boolean loaded = false;
090:
091: public static void loadLibraries() {
092: if (!loaded) {
093: java.security.AccessController
094: .doPrivileged(new sun.security.action.LoadLibraryAction(
095: "awt"));
096: loaded = true;
097: }
098: }
099:
100: static {
101: loadLibraries();
102: // Force Win32GE to load if it is not already loaded; this loads
103: // various other classes that are required for basic awt functionality
104: Win32GraphicsEnvironment.init();
105: initIDs();
106:
107: // Print out which version of Windows is running
108: if (dbg.on) {
109: printWindowsVersion();
110: }
111:
112: java.security.AccessController
113: .doPrivileged(new java.security.PrivilegedAction() {
114: public Object run() {
115: String browserProp = System
116: .getProperty("browser");
117: if (browserProp != null
118: && browserProp.equals("sun.plugin")) {
119: disableCustomPalette();
120: }
121: return null;
122: }
123: });
124: }
125:
126: private static native void printWindowsVersion();
127:
128: private static native void disableCustomPalette();
129:
130: /*
131: * Reset the static GraphicsConfiguration to the default. Called on
132: * startup and when display settings have changed.
133: */
134: public static void resetGC() {
135: if (GraphicsEnvironment.isHeadless()) {
136: config = null;
137: } else {
138: config = (GraphicsEnvironment.getLocalGraphicsEnvironment()
139: .getDefaultScreenDevice().getDefaultConfiguration());
140: }
141: }
142:
143: /*
144: * NOTE: The following embedded*() methods are non-public API intended
145: * for internal use only. The methods are unsupported and could go
146: * away in future releases.
147: *
148: * New hook functions for using the AWT as an embedded service. These
149: * functions replace the global C function AwtInit() which was previously
150: * exported by awt.dll.
151: *
152: * When used as an embedded service, the AWT does NOT have its own
153: * message pump. It instead relies on the parent application to provide
154: * this functionality. embeddedInit() assumes that the thread on which it
155: * is called is the message pumping thread. Violating this assumption
156: * will lead to undefined behavior.
157: *
158: * embeddedInit must be called before the WToolkit() constructor.
159: * embeddedDispose should be called before the applicaton terminates the
160: * Java VM. It is currently unsafe to reinitialize the toolkit again
161: * after it has been disposed. Instead, awt.dll must be reloaded and the
162: * class loader which loaded WToolkit must be finalized before it is
163: * safe to reuse AWT. Dynamic reusability may be added to the toolkit in
164: * the future.
165: */
166:
167: /**
168: * Initializes the Toolkit for use in an embedded environment.
169: *
170: * @return true if the the initialization succeeded; false if it failed.
171: * The function will fail if the Toolkit was already initialized.
172: * @since 1.3
173: */
174: public static native boolean embeddedInit();
175:
176: /**
177: * Disposes the Toolkit in an embedded environment. This method should
178: * not be called on exit unless the Toolkit was constructed with
179: * embeddedInit.
180: *
181: * @return true if the disposal succeeded; false if it failed. The
182: * function will fail if the calling thread is not the same
183: * thread which called embeddedInit(), or if the Toolkit was
184: * already disposed.
185: * @since 1.3
186: */
187: public static native boolean embeddedDispose();
188:
189: /**
190: * To be called after processing the event queue by users of the above
191: * embeddedInit() function. The reason for this additional call is that
192: * there are some operations performed during idle time in the AwtToolkit
193: * event loop which should also be performed during idle time in any
194: * other native event loop. Failure to do so could result in
195: * deadlocks.
196: *
197: * This method was added at the last minute of the jdk1.4 release
198: * to work around a specific customer problem. As with the above
199: * embedded*() class, this method is non-public and should not be
200: * used by external applications.
201: *
202: * See bug #4526587 for more information.
203: */
204: public native void embeddedEventLoopIdleProcessing();
205:
206: public static final String DATA_TRANSFERER_CLASS_NAME = "sun.awt.windows.WDataTransferer";
207:
208: static class ToolkitDisposer implements sun.java2d.DisposerRecord {
209: public void dispose() {
210: WToolkit.postDispose();
211: }
212: }
213:
214: private final Object anchor = new Object();
215:
216: private static native void postDispose();
217:
218: public WToolkit() {
219: // Startup toolkit threads
220: if (PerformanceLogger.loggingEnabled()) {
221: PerformanceLogger.setTime("WToolkit construction");
222: }
223:
224: sun.java2d.Disposer.addRecord(anchor, new ToolkitDisposer());
225:
226: synchronized (this ) {
227: // Fix for bug #4046430 -- Race condition
228: // where notifyAll can be called before
229: // the "AWT-Windows" thread's parent thread is
230: // waiting, resulting in a deadlock on startup.
231: Thread toolkitThread = new Thread(this , "AWT-Windows");
232: toolkitThread.setDaemon(true);
233: toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);
234:
235: /*
236: * Fix for 4701990.
237: * AWTAutoShutdown state must be changed before the toolkit thread
238: * starts to avoid race condition.
239: */
240: AWTAutoShutdown.notifyToolkitThreadBusy();
241:
242: toolkitThread.start();
243:
244: try {
245: wait();
246: } catch (InterruptedException x) {
247: }
248: }
249: SunToolkit
250: .setDataTransfererClassName(DATA_TRANSFERER_CLASS_NAME);
251:
252: // Enabled "live resizing" by default. It remains controlled
253: // by the native system though.
254: setDynamicLayout(true);
255: }
256:
257: public void run() {
258: boolean startPump = init();
259:
260: if (startPump) {
261: ThreadGroup mainTG = (ThreadGroup) AccessController
262: .doPrivileged(new PrivilegedAction() {
263: public Object run() {
264: ThreadGroup currentTG = Thread
265: .currentThread().getThreadGroup();
266: ThreadGroup parentTG = currentTG
267: .getParent();
268: while (parentTG != null) {
269: currentTG = parentTG;
270: parentTG = currentTG.getParent();
271: }
272: return currentTG;
273: }
274: });
275:
276: Runtime.getRuntime().addShutdownHook(
277: new Thread(mainTG, new Runnable() {
278: public void run() {
279: shutdown();
280: }
281: }));
282: }
283:
284: synchronized (this ) {
285: notifyAll();
286: }
287:
288: if (startPump) {
289: eventLoop(); // will Dispose Toolkit when shutdown hook executes
290: }
291: }
292:
293: /*
294: * eventLoop() begins the native message pump which retrieves and processes
295: * native events.
296: *
297: * When shutdown() is called by the ShutdownHook added in run(), a
298: * WM_QUIT message is posted to the Toolkit thread indicating that
299: * eventLoop() should Dispose the toolkit and exit.
300: */
301: private native boolean init();
302:
303: private native void eventLoop();
304:
305: private native void shutdown();
306:
307: /*
308: * Instead of blocking the "AWT-Windows" thread uselessly on a semaphore,
309: * use these functions. startSecondaryEventLoop() corresponds to wait()
310: * and quitSecondaryEventLoop() corresponds to notify.
311: *
312: * These functions simulate blocking while allowing the AWT to continue
313: * processing native events, eliminating a potential deadlock situation
314: * with SendMessage.
315: *
316: * WARNING: startSecondaryEventLoop must only be called from the "AWT-
317: * Windows" thread.
318: */
319: public static native void startSecondaryEventLoop();
320:
321: public static native void quitSecondaryEventLoop();
322:
323: /*
324: * Create peer objects.
325: */
326:
327: public ButtonPeer createButton(Button target) {
328: ButtonPeer peer = new WButtonPeer(target);
329: targetCreatedPeer(target, peer);
330: return peer;
331: }
332:
333: public TextFieldPeer createTextField(TextField target) {
334: TextFieldPeer peer = new WTextFieldPeer(target);
335: targetCreatedPeer(target, peer);
336: return peer;
337: }
338:
339: public LabelPeer createLabel(Label target) {
340: LabelPeer peer = new WLabelPeer(target);
341: targetCreatedPeer(target, peer);
342: return peer;
343: }
344:
345: public ListPeer createList(List target) {
346: ListPeer peer = new WListPeer(target);
347: targetCreatedPeer(target, peer);
348: return peer;
349: }
350:
351: public CheckboxPeer createCheckbox(Checkbox target) {
352: CheckboxPeer peer = new WCheckboxPeer(target);
353: targetCreatedPeer(target, peer);
354: return peer;
355: }
356:
357: public ScrollbarPeer createScrollbar(Scrollbar target) {
358: ScrollbarPeer peer = new WScrollbarPeer(target);
359: targetCreatedPeer(target, peer);
360: return peer;
361: }
362:
363: public ScrollPanePeer createScrollPane(ScrollPane target) {
364: ScrollPanePeer peer = new WScrollPanePeer(target);
365: targetCreatedPeer(target, peer);
366: return peer;
367: }
368:
369: public TextAreaPeer createTextArea(TextArea target) {
370: TextAreaPeer peer = new WTextAreaPeer(target);
371: targetCreatedPeer(target, peer);
372: return peer;
373: }
374:
375: public ChoicePeer createChoice(Choice target) {
376: ChoicePeer peer = new WChoicePeer(target);
377: targetCreatedPeer(target, peer);
378: return peer;
379: }
380:
381: public FramePeer createFrame(Frame target) {
382: FramePeer peer = new WFramePeer(target);
383: targetCreatedPeer(target, peer);
384: return peer;
385: }
386:
387: public CanvasPeer createCanvas(Canvas target) {
388: CanvasPeer peer = new WCanvasPeer(target);
389: targetCreatedPeer(target, peer);
390: return peer;
391: }
392:
393: public void disableBackgroundErase(Canvas canvas) {
394: WCanvasPeer peer = (WCanvasPeer) canvas.getPeer();
395: if (peer == null) {
396: throw new IllegalStateException(
397: "Canvas must have a valid peer");
398: }
399: peer.disableBackgroundErase();
400: }
401:
402: public PanelPeer createPanel(Panel target) {
403: PanelPeer peer = new WPanelPeer(target);
404: targetCreatedPeer(target, peer);
405: return peer;
406: }
407:
408: public WindowPeer createWindow(Window target) {
409: WindowPeer peer = new WWindowPeer(target);
410: targetCreatedPeer(target, peer);
411: return peer;
412: }
413:
414: public DialogPeer createDialog(Dialog target) {
415: DialogPeer peer = new WDialogPeer(target);
416: targetCreatedPeer(target, peer);
417: return peer;
418: }
419:
420: public FileDialogPeer createFileDialog(FileDialog target) {
421: FileDialogPeer peer = new WFileDialogPeer(target);
422: targetCreatedPeer(target, peer);
423: return peer;
424: }
425:
426: public MenuBarPeer createMenuBar(MenuBar target) {
427: MenuBarPeer peer = new WMenuBarPeer(target);
428: targetCreatedPeer(target, peer);
429: return peer;
430: }
431:
432: public MenuPeer createMenu(Menu target) {
433: MenuPeer peer = new WMenuPeer(target);
434: targetCreatedPeer(target, peer);
435: return peer;
436: }
437:
438: public PopupMenuPeer createPopupMenu(PopupMenu target) {
439: PopupMenuPeer peer = new WPopupMenuPeer(target);
440: targetCreatedPeer(target, peer);
441: return peer;
442: }
443:
444: public MenuItemPeer createMenuItem(MenuItem target) {
445: MenuItemPeer peer = new WMenuItemPeer(target);
446: targetCreatedPeer(target, peer);
447: return peer;
448: }
449:
450: public CheckboxMenuItemPeer createCheckboxMenuItem(
451: CheckboxMenuItem target) {
452: CheckboxMenuItemPeer peer = new WCheckboxMenuItemPeer(target);
453: targetCreatedPeer(target, peer);
454: return peer;
455: }
456:
457: public RobotPeer createRobot(Robot target, GraphicsDevice screen) {
458: // (target is unused for now)
459: // Robot's don't need to go in the peer map since
460: // they're not Component's
461: return new WRobotPeer(screen);
462: }
463:
464: public WEmbeddedFramePeer createEmbeddedFrame(WEmbeddedFrame target) {
465: WEmbeddedFramePeer peer = new WEmbeddedFramePeer(target);
466: targetCreatedPeer(target, peer);
467: return peer;
468: }
469:
470: WPrintDialogPeer createWPrintDialog(WPrintDialog target) {
471: WPrintDialogPeer peer = new WPrintDialogPeer(target);
472: targetCreatedPeer(target, peer);
473: return peer;
474: }
475:
476: WPageDialogPeer createWPageDialog(WPageDialog target) {
477: WPageDialogPeer peer = new WPageDialogPeer(target);
478: targetCreatedPeer(target, peer);
479: return peer;
480: }
481:
482: public TrayIconPeer createTrayIcon(TrayIcon target) {
483: WTrayIconPeer peer = new WTrayIconPeer(target);
484: targetCreatedPeer(target, peer);
485: return peer;
486: }
487:
488: public SystemTrayPeer createSystemTray(SystemTray target) {
489: return new WSystemTrayPeer(target);
490: }
491:
492: public boolean isTraySupported() {
493: return true;
494: }
495:
496: protected native void setDynamicLayoutNative(boolean b);
497:
498: public void setDynamicLayout(boolean b) {
499: if (b == dynamicLayoutSetting) {
500: return;
501: }
502:
503: dynamicLayoutSetting = b;
504: setDynamicLayoutNative(b);
505: }
506:
507: protected boolean isDynamicLayoutSet() {
508: return dynamicLayoutSetting;
509: }
510:
511: /*
512: * Called from lazilyLoadDynamicLayoutSupportedProperty because
513: * Windows doesn't always send WM_SETTINGCHANGE when it should.
514: */
515: protected native boolean isDynamicLayoutSupportedNative();
516:
517: public boolean isDynamicLayoutActive() {
518: return (isDynamicLayoutSet() && isDynamicLayoutSupported());
519: }
520:
521: /**
522: * Returns <code>true</code> if this frame state is supported.
523: */
524: public boolean isFrameStateSupported(int state) {
525: switch (state) {
526: case Frame.NORMAL:
527: case Frame.ICONIFIED:
528: case Frame.MAXIMIZED_BOTH:
529: return true;
530: default:
531: return false;
532: }
533: }
534:
535: static native ColorModel makeColorModel();
536:
537: static ColorModel screenmodel;
538:
539: static ColorModel getStaticColorModel() {
540: if (GraphicsEnvironment.isHeadless()) {
541: throw new IllegalArgumentException();
542: }
543: if (config == null) {
544: resetGC();
545: }
546: return config.getColorModel();
547: }
548:
549: public ColorModel getColorModel() {
550: return getStaticColorModel();
551: }
552:
553: public Insets getScreenInsets(GraphicsConfiguration gc) {
554: return getScreenInsets(((Win32GraphicsDevice) gc.getDevice())
555: .getScreen());
556: }
557:
558: public int getScreenResolution() {
559: Win32GraphicsEnvironment ge = (Win32GraphicsEnvironment) GraphicsEnvironment
560: .getLocalGraphicsEnvironment();
561: return ge.getXResolution();
562: }
563:
564: protected native int getScreenWidth();
565:
566: protected native int getScreenHeight();
567:
568: protected native Insets getScreenInsets(int screen);
569:
570: public FontMetrics getFontMetrics(Font font) {
571: // REMIND: platform font flag should be removed post-merlin.
572: if (sun.font.FontManager.usePlatformFontMetrics()) {
573: return WFontMetrics.getFontMetrics(font);
574: }
575: return super .getFontMetrics(font);
576: }
577:
578: public FontPeer getFontPeer(String name, int style) {
579: FontPeer retval = null;
580: String lcName = name.toLowerCase();
581: if (null != cacheFontPeer) {
582: retval = (FontPeer) cacheFontPeer.get(lcName + style);
583: if (null != retval) {
584: return retval;
585: }
586: }
587: retval = new WFontPeer(name, style);
588: if (retval != null) {
589: if (null == cacheFontPeer) {
590: cacheFontPeer = new Hashtable(5, (float) 0.9);
591: }
592: if (null != cacheFontPeer) {
593: cacheFontPeer.put(lcName + style, retval);
594: }
595: }
596: return retval;
597: }
598:
599: private native void nativeSync();
600:
601: public void sync() {
602: // flush the GDI/DD buffers
603: nativeSync();
604: // now flush the OGL pipeline (this is a no-op if OGL is not enabled)
605: OGLRenderQueue.sync();
606: }
607:
608: public PrintJob getPrintJob(Frame frame, String doctitle,
609: Properties props) {
610: return getPrintJob(frame, doctitle, null, null);
611: }
612:
613: public PrintJob getPrintJob(Frame frame, String doctitle,
614: JobAttributes jobAttributes, PageAttributes pageAttributes) {
615:
616: if (GraphicsEnvironment.isHeadless()) {
617: throw new IllegalArgumentException();
618: }
619:
620: PrintJob2D printJob = new PrintJob2D(frame, doctitle,
621: jobAttributes, pageAttributes);
622:
623: if (printJob.printDialog() == false) {
624: printJob = null;
625: }
626:
627: return printJob;
628: }
629:
630: public native void beep();
631:
632: public boolean getLockingKeyState(int key) {
633: if (!(key == KeyEvent.VK_CAPS_LOCK
634: || key == KeyEvent.VK_NUM_LOCK
635: || key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) {
636: throw new IllegalArgumentException(
637: "invalid key for Toolkit.getLockingKeyState");
638: }
639: return getLockingKeyStateNative(key);
640: }
641:
642: public native boolean getLockingKeyStateNative(int key);
643:
644: public void setLockingKeyState(int key, boolean on) {
645: if (!(key == KeyEvent.VK_CAPS_LOCK
646: || key == KeyEvent.VK_NUM_LOCK
647: || key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) {
648: throw new IllegalArgumentException(
649: "invalid key for Toolkit.setLockingKeyState");
650: }
651: setLockingKeyStateNative(key, on);
652: }
653:
654: public native void setLockingKeyStateNative(int key, boolean on);
655:
656: public Clipboard getSystemClipboard() {
657: SecurityManager security = System.getSecurityManager();
658: if (security != null) {
659: security.checkSystemClipboardAccess();
660: }
661: synchronized (this ) {
662: if (clipboard == null) {
663: clipboard = new WClipboard();
664: }
665: }
666: return clipboard;
667: }
668:
669: protected native void loadSystemColors(int[] systemColors);
670:
671: public static final Object targetToPeer(Object target) {
672: return SunToolkit.targetToPeer(target);
673: }
674:
675: public static final void targetDisposedPeer(Object target,
676: Object peer) {
677: SunToolkit.targetDisposedPeer(target, peer);
678: }
679:
680: /**
681: * Returns a new input method adapter descriptor for native input methods.
682: */
683: public InputMethodDescriptor getInputMethodAdapterDescriptor() {
684: return new WInputMethodDescriptor();
685: }
686:
687: /**
688: * Returns a style map for the input method highlight.
689: */
690: public Map mapInputMethodHighlight(InputMethodHighlight highlight) {
691: return WInputMethod.mapInputMethodHighlight(highlight);
692: }
693:
694: /**
695: * Returns whether enableInputMethods should be set to true for peered
696: * TextComponent instances on this platform.
697: */
698: public boolean enableInputMethodsForTextComponent() {
699: return true;
700: }
701:
702: /**
703: * Returns the default keyboard locale of the underlying operating system
704: */
705: public Locale getDefaultKeyboardLocale() {
706: Locale locale = WInputMethod.getNativeLocale();
707:
708: if (locale == null) {
709: return super .getDefaultKeyboardLocale();
710: } else {
711: return locale;
712: }
713: }
714:
715: /**
716: * Returns a new custom cursor.
717: */
718: public Cursor createCustomCursor(Image cursor, Point hotSpot,
719: String name) throws IndexOutOfBoundsException {
720: return new WCustomCursor(cursor, hotSpot, name);
721: }
722:
723: /**
724: * Returns the supported cursor size (Win32 only has one).
725: */
726: public Dimension getBestCursorSize(int preferredWidth,
727: int preferredHeight) {
728: return new Dimension(WCustomCursor.getCursorWidth(),
729: WCustomCursor.getCursorHeight());
730: }
731:
732: public native int getMaximumCursorColors();
733:
734: static void paletteChanged() {
735: ((Win32GraphicsEnvironment) GraphicsEnvironment
736: .getLocalGraphicsEnvironment()).paletteChanged();
737: }
738:
739: /*
740: * Called from Toolkit native code when a WM_DISPLAYCHANGE occurs.
741: * Have Win32GraphicsEnvironment execute the display change code on the
742: * Event thread.
743: */
744: static public void displayChanged() {
745: EventQueue.invokeLater(new Runnable() {
746: public void run() {
747: ((Win32GraphicsEnvironment) GraphicsEnvironment
748: .getLocalGraphicsEnvironment())
749: .displayChanged();
750: }
751: });
752: }
753:
754: /**
755: * create the peer for a DragSourceContext
756: */
757:
758: public DragSourceContextPeer createDragSourceContextPeer(
759: DragGestureEvent dge) throws InvalidDnDOperationException {
760: return WDragSourceContextPeer.createDragSourceContextPeer(dge);
761: }
762:
763: public <T extends DragGestureRecognizer> T createDragGestureRecognizer(
764: Class<T> abstractRecognizerClass, DragSource ds,
765: Component c, int srcActions, DragGestureListener dgl) {
766: if (MouseDragGestureRecognizer.class
767: .equals(abstractRecognizerClass))
768: return (T) new WMouseDragGestureRecognizer(ds, c,
769: srcActions, dgl);
770: else
771: return null;
772: }
773:
774: /**
775: *
776: */
777:
778: private static final String prefix = "DnD.Cursor.";
779: private static final String postfix = ".32x32";
780: private static final String awtPrefix = "awt.";
781: private static final String dndPrefix = "DnD.";
782:
783: protected Object lazilyLoadDesktopProperty(String name) {
784: if (name.startsWith(prefix)) {
785: String cursorName = name.substring(prefix.length(), name
786: .length())
787: + postfix;
788:
789: try {
790: return Cursor.getSystemCustomCursor(cursorName);
791: } catch (AWTException awte) {
792: throw new RuntimeException(
793: "cannot load system cursor: " + cursorName,
794: awte);
795: }
796: }
797:
798: if (name.equals("awt.dynamicLayoutSupported")) {
799: return Boolean.valueOf(isDynamicLayoutSupported());
800: }
801:
802: if (WDesktopProperties.isWindowsProperty(name)
803: || name.startsWith(awtPrefix)
804: || name.startsWith(dndPrefix)) {
805: synchronized (this ) {
806: lazilyInitWProps();
807: return desktopProperties.get(name);
808: }
809: }
810:
811: return super .lazilyLoadDesktopProperty(name);
812: }
813:
814: private synchronized void lazilyInitWProps() {
815: if (wprops == null) {
816: wprops = new WDesktopProperties(this );
817: updateProperties();
818: }
819: }
820:
821: /*
822: * Called from lazilyLoadDesktopProperty because Windows doesn't
823: * always send WM_SETTINGCHANGE when it should.
824: */
825: private synchronized boolean isDynamicLayoutSupported() {
826: boolean nativeDynamic = isDynamicLayoutSupportedNative();
827: lazilyInitWProps();
828: Boolean prop = (Boolean) desktopProperties
829: .get("awt.dynamicLayoutSupported");
830:
831: if (log.isLoggable(Level.FINE)) {
832: log.fine("In WTK.isDynamicLayoutSupported()"
833: + " nativeDynamic == " + nativeDynamic
834: + " wprops.dynamic == " + prop);
835: }
836:
837: if ((prop == null) || (nativeDynamic != prop.booleanValue())) {
838: // We missed the WM_SETTINGCHANGE, so we pretend
839: // we just got one - fire the propertyChange, etc.
840: windowsSettingChange();
841: return nativeDynamic;
842: }
843:
844: return prop.booleanValue();
845: }
846:
847: /*
848: * Called from native toolkit code when WM_SETTINGCHANGE message received
849: * Also called from lazilyLoadDynamicLayoutSupportedProperty because
850: * Windows doesn't always send WM_SETTINGCHANGE when it should.
851: */
852: private void windowsSettingChange() {
853: EventQueue.invokeLater(new Runnable() {
854: public void run() {
855: updateProperties();
856: }
857: });
858: }
859:
860: private synchronized void updateProperties() {
861: if (null == wprops) {
862: // wprops has not been initialized, so we have nothing to update
863: return;
864: }
865:
866: Map<String, Object> props = wprops.getProperties();
867: for (String propName : props.keySet()) {
868: Object val = props.get(propName);
869: if (log.isLoggable(Level.FINE)) {
870: log.fine("changed " + propName + " to " + val);
871: }
872: setDesktopProperty(propName, val);
873: }
874: }
875:
876: public synchronized void addPropertyChangeListener(String name,
877: PropertyChangeListener pcl) {
878: if (WDesktopProperties.isWindowsProperty(name)
879: || name.startsWith(awtPrefix)
880: || name.startsWith(dndPrefix)) {
881: // someone is interested in Windows-specific desktop properties
882: // we should initialize wprops
883: lazilyInitWProps();
884: }
885: super .addPropertyChangeListener(name, pcl);
886: }
887:
888: /*
889: * initialize only static props here and do not try to initialize props which depends on wprops,
890: * this should be done in lazilyLoadDesktopProperty() only.
891: */
892: protected synchronized void initializeDesktopProperties() {
893: desktopProperties.put("DnD.Autoscroll.initialDelay", Integer
894: .valueOf(50));
895: desktopProperties.put("DnD.Autoscroll.interval", Integer
896: .valueOf(50));
897:
898: try {
899: desktopProperties.put("Shell.shellFolderManager", Class
900: .forName("sun.awt.shell.Win32ShellFolderManager2"));
901: } catch (ClassNotFoundException ex) {
902: }
903: }
904:
905: /*
906: * This returns the value for the desktop property "awt.font.desktophints"
907: * This requires that the Windows properties have already been gathered.
908: */
909: protected synchronized RenderingHints getDesktopAAHints() {
910: if (wprops == null) {
911: return null;
912: } else {
913: return wprops.getDesktopAAHints();
914: }
915: }
916:
917: public boolean isModalityTypeSupported(
918: 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(
927: Dialog.ModalExclusionType exclusionType) {
928: return (exclusionType == null)
929: || (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE)
930: || (exclusionType == Dialog.ModalExclusionType.APPLICATION_EXCLUDE)
931: || (exclusionType == Dialog.ModalExclusionType.TOOLKIT_EXCLUDE);
932: }
933:
934: public static WToolkit getWToolkit() {
935: WToolkit toolkit = (WToolkit) Toolkit.getDefaultToolkit();
936: return toolkit;
937: }
938:
939: public boolean useBufferPerWindow() {
940: return true;
941: }
942:
943: public void grab(Window w) {
944: if (w.getPeer() != null) {
945: ((WWindowPeer) w.getPeer()).grab();
946: }
947: }
948:
949: public void ungrab(Window w) {
950: if (w.getPeer() != null) {
951: ((WWindowPeer) w.getPeer()).ungrab();
952: }
953: }
954:
955: public native boolean syncNativeQueue(final long timeout);
956:
957: public boolean isDesktopSupported() {
958: return true;
959: }
960:
961: public DesktopPeer createDesktopPeer(Desktop target) {
962: return new WDesktopPeer();
963: }
964:
965: }
|