001: /*
002: * Copyright 1995-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.motif;
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.datatransfer.Clipboard;
034: import java.awt.event.*;
035: import java.lang.reflect.*;
036: import java.lang.Math;
037: import java.io.*;
038: import java.security.AccessController;
039: import java.security.PrivilegedAction;
040: import java.security.PrivilegedActionException;
041: import java.security.PrivilegedExceptionAction;
042: import java.util.Properties;
043: import java.util.Map;
044: import java.util.Iterator;
045:
046: import sun.awt.AppContext;
047: import sun.awt.AWTAutoShutdown;
048: import sun.awt.SunToolkit;
049: import sun.awt.UNIXToolkit;
050: import sun.awt.GlobalCursorManager;
051: import sun.awt.DebugHelper;
052: import sun.awt.datatransfer.DataTransferer;
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.awt.motif.MInputMethod;
063: import sun.awt.X11GraphicsConfig;
064: import sun.awt.X11GraphicsEnvironment;
065: import sun.awt.XSettings;
066:
067: import sun.awt.motif.MDragSourceContextPeer;
068:
069: import sun.print.PrintJob2D;
070:
071: import sun.misc.PerformanceLogger;
072: import sun.misc.Unsafe;
073:
074: import sun.security.action.GetBooleanAction;
075:
076: public class MToolkit extends UNIXToolkit implements Runnable {
077: private static final DebugHelper dbg = DebugHelper
078: .create(MToolkit.class);
079:
080: // the system clipboard - CLIPBOARD selection
081: X11Clipboard clipboard;
082: // the system selection - PRIMARY selection
083: X11Clipboard selection;
084:
085: // Dynamic Layout Resize client code setting
086: protected static boolean dynamicLayoutSetting = false;
087:
088: /**
089: * True when the x settings have been loaded.
090: */
091: private boolean loadedXSettings;
092:
093: /**
094: * XSETTINGS for the default screen.
095: * <p>
096: * <strong>XXX:</strong> see <code>MToolkit.parseXSettings</code>
097: * and <code>awt_xsettings_update</code> in
098: * <samp>awt_MToolkit.c</samp>
099: */
100: private XSettings xs;
101:
102: /*
103: * Note: The MToolkit object depends on the static initializer
104: * of X11GraphicsEnvironment to initialize the connection to
105: * the X11 server.
106: */
107: static final X11GraphicsConfig config;
108:
109: private static final boolean motifdnd;
110:
111: static {
112: if (GraphicsEnvironment.isHeadless()) {
113: config = null;
114: } else {
115: config = (X11GraphicsConfig) (GraphicsEnvironment
116: .getLocalGraphicsEnvironment()
117: .getDefaultScreenDevice().getDefaultConfiguration());
118: }
119:
120: /* Add font properties font directories to the X11 font path.
121: * Its called here *after* the X connection has been initialised
122: * and when we know that MToolkit is the one that will be used,
123: * since XToolkit doesn't need the X11 font path set
124: */
125: X11GraphicsEnvironment.setNativeFontPath();
126:
127: motifdnd = ((Boolean) java.security.AccessController
128: .doPrivileged(new GetBooleanAction("awt.dnd.motifdnd")))
129: .booleanValue();
130: }
131:
132: public static final String DATA_TRANSFERER_CLASS_NAME = "sun.awt.motif.MDataTransferer";
133:
134: public MToolkit() {
135: super ();
136: if (PerformanceLogger.loggingEnabled()) {
137: PerformanceLogger.setTime("MToolkit construction");
138: }
139: if (!GraphicsEnvironment.isHeadless()) {
140: String mainClassName = null;
141:
142: StackTraceElement trace[] = (new Throwable())
143: .getStackTrace();
144: int bottom = trace.length - 1;
145: if (bottom >= 0) {
146: mainClassName = trace[bottom].getClassName();
147: }
148: if (mainClassName == null || mainClassName.equals("")) {
149: mainClassName = "AWT";
150: }
151:
152: init(mainClassName);
153: SunToolkit
154: .setDataTransfererClassName(DATA_TRANSFERER_CLASS_NAME);
155:
156: Thread toolkitThread = new Thread(this , "AWT-Motif");
157: toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);
158: toolkitThread.setDaemon(true);
159: ThreadGroup mainTG = (ThreadGroup) AccessController
160: .doPrivileged(new PrivilegedAction() {
161: public Object run() {
162: ThreadGroup currentTG = Thread
163: .currentThread().getThreadGroup();
164: ThreadGroup parentTG = currentTG
165: .getParent();
166: while (parentTG != null) {
167: currentTG = parentTG;
168: parentTG = currentTG.getParent();
169: }
170: return currentTG;
171: }
172: });
173:
174: Runtime.getRuntime().addShutdownHook(
175: new Thread(mainTG, new Runnable() {
176: public void run() {
177: shutdown();
178: }
179: }, "Shutdown-Thread"));
180:
181: /*
182: * Fix for 4701990.
183: * AWTAutoShutdown state must be changed before the toolkit thread
184: * starts to avoid race condition.
185: */
186: AWTAutoShutdown.notifyToolkitThreadBusy();
187:
188: toolkitThread.start();
189: }
190: }
191:
192: public native void init(String mainClassName);
193:
194: public native void run();
195:
196: private native void shutdown();
197:
198: /*
199: * Create peer objects.
200: */
201:
202: public ButtonPeer createButton(Button target) {
203: ButtonPeer peer = new MButtonPeer(target);
204: targetCreatedPeer(target, peer);
205: return peer;
206: }
207:
208: public TextFieldPeer createTextField(TextField target) {
209: TextFieldPeer peer = new MTextFieldPeer(target);
210: targetCreatedPeer(target, peer);
211: return peer;
212: }
213:
214: public LabelPeer createLabel(Label target) {
215: LabelPeer peer = new MLabelPeer(target);
216: targetCreatedPeer(target, peer);
217: return peer;
218: }
219:
220: public ListPeer createList(List target) {
221: ListPeer peer = new MListPeer(target);
222: targetCreatedPeer(target, peer);
223: return peer;
224: }
225:
226: public CheckboxPeer createCheckbox(Checkbox target) {
227: CheckboxPeer peer = new MCheckboxPeer(target);
228: targetCreatedPeer(target, peer);
229: return peer;
230: }
231:
232: public ScrollbarPeer createScrollbar(Scrollbar target) {
233: ScrollbarPeer peer = new MScrollbarPeer(target);
234: targetCreatedPeer(target, peer);
235: return peer;
236: }
237:
238: public ScrollPanePeer createScrollPane(ScrollPane target) {
239: ScrollPanePeer peer = new MScrollPanePeer(target);
240: targetCreatedPeer(target, peer);
241: return peer;
242: }
243:
244: public TextAreaPeer createTextArea(TextArea target) {
245: TextAreaPeer peer = new MTextAreaPeer(target);
246: targetCreatedPeer(target, peer);
247: return peer;
248: }
249:
250: public ChoicePeer createChoice(Choice target) {
251: ChoicePeer peer = new MChoicePeer(target);
252: targetCreatedPeer(target, peer);
253: return peer;
254: }
255:
256: public FramePeer createFrame(Frame target) {
257: FramePeer peer = new MFramePeer(target);
258: targetCreatedPeer(target, peer);
259: return peer;
260: }
261:
262: public CanvasPeer createCanvas(Canvas target) {
263: CanvasPeer peer = (isXEmbedServerRequested() ? new MEmbedCanvasPeer(
264: target)
265: : new MCanvasPeer(target));
266: targetCreatedPeer(target, peer);
267: return peer;
268: }
269:
270: public PanelPeer createPanel(Panel target) {
271: PanelPeer peer = new MPanelPeer(target);
272: targetCreatedPeer(target, peer);
273: return peer;
274: }
275:
276: public WindowPeer createWindow(Window target) {
277: WindowPeer peer = new MWindowPeer(target);
278: targetCreatedPeer(target, peer);
279: return peer;
280: }
281:
282: public DialogPeer createDialog(Dialog target) {
283: DialogPeer peer = new MDialogPeer(target);
284: targetCreatedPeer(target, peer);
285: return peer;
286: }
287:
288: public FileDialogPeer createFileDialog(FileDialog target) {
289: FileDialogPeer peer = new MFileDialogPeer(target);
290: targetCreatedPeer(target, peer);
291: return peer;
292: }
293:
294: public MenuBarPeer createMenuBar(MenuBar target) {
295: MenuBarPeer peer = new MMenuBarPeer(target);
296: targetCreatedPeer(target, peer);
297: return peer;
298: }
299:
300: public MenuPeer createMenu(Menu target) {
301: MenuPeer peer = new MMenuPeer(target);
302: targetCreatedPeer(target, peer);
303: return peer;
304: }
305:
306: public PopupMenuPeer createPopupMenu(PopupMenu target) {
307: PopupMenuPeer peer = new MPopupMenuPeer(target);
308: targetCreatedPeer(target, peer);
309: return peer;
310: }
311:
312: public MenuItemPeer createMenuItem(MenuItem target) {
313: MenuItemPeer peer = new MMenuItemPeer(target);
314: targetCreatedPeer(target, peer);
315: return peer;
316: }
317:
318: public CheckboxMenuItemPeer createCheckboxMenuItem(
319: CheckboxMenuItem target) {
320: CheckboxMenuItemPeer peer = new MCheckboxMenuItemPeer(target);
321: targetCreatedPeer(target, peer);
322: return peer;
323: }
324:
325: public MEmbeddedFramePeer createEmbeddedFrame(MEmbeddedFrame target) {
326: MEmbeddedFramePeer peer = new MEmbeddedFramePeer(target);
327: targetCreatedPeer(target, peer);
328: return peer;
329: }
330:
331: public FontPeer getFontPeer(String name, int style) {
332: return new MFontPeer(name, style);
333: }
334:
335: /*
336: * On X, support for dynamic layout on resizing is governed by the
337: * window manager. If the window manager supports it, it happens
338: * automatically. The setter method for this property is
339: * irrelevant on X.
340: */
341: public void setDynamicLayout(boolean b) {
342: dynamicLayoutSetting = b;
343: }
344:
345: protected boolean isDynamicLayoutSet() {
346: return dynamicLayoutSetting;
347: }
348:
349: /* Called from isDynamicLayoutActive() and from
350: * lazilyLoadDynamicLayoutSupportedProperty()
351: */
352: protected native boolean isDynamicLayoutSupportedNative();
353:
354: public boolean isDynamicLayoutActive() {
355: return isDynamicLayoutSupportedNative();
356: }
357:
358: public native boolean isFrameStateSupported(int state);
359:
360: public TrayIconPeer createTrayIcon(TrayIcon target)
361: throws HeadlessException {
362: return null;
363: }
364:
365: public SystemTrayPeer createSystemTray(SystemTray target)
366: throws HeadlessException {
367: return null;
368: }
369:
370: public boolean isTraySupported() {
371: return false;
372: }
373:
374: static native ColorModel makeColorModel();
375:
376: static ColorModel screenmodel;
377:
378: static ColorModel getStaticColorModel() {
379: if (screenmodel == null) {
380: screenmodel = config.getColorModel();
381: }
382: return screenmodel;
383: }
384:
385: public ColorModel getColorModel() {
386: return getStaticColorModel();
387: }
388:
389: public native int getScreenResolution();
390:
391: public Insets getScreenInsets(GraphicsConfiguration gc) {
392: return new Insets(0, 0, 0, 0);
393: }
394:
395: protected native int getScreenWidth();
396:
397: protected native int getScreenHeight();
398:
399: public FontMetrics getFontMetrics(Font font) {
400: /*
401: // REMIND: platform font flag should be obsolete soon
402: if (!RasterOutputManager.usesPlatformFont()) {
403: return super.getFontMetrics(font);
404: } else {
405: return X11FontMetrics.getFontMetrics(font);
406: }
407: */
408: return super .getFontMetrics(font);
409: }
410:
411: public PrintJob getPrintJob(final Frame frame,
412: final String doctitle, final Properties props) {
413:
414: if (GraphicsEnvironment.isHeadless()) {
415: throw new IllegalArgumentException();
416: }
417:
418: PrintJob2D printJob = new PrintJob2D(frame, doctitle, props);
419:
420: if (printJob.printDialog() == false) {
421: printJob = null;
422: }
423:
424: return printJob;
425: }
426:
427: public PrintJob getPrintJob(final Frame frame,
428: final String doctitle, final JobAttributes jobAttributes,
429: final PageAttributes pageAttributes) {
430:
431: if (GraphicsEnvironment.isHeadless()) {
432: throw new IllegalArgumentException();
433: }
434:
435: PrintJob2D printJob = new PrintJob2D(frame, doctitle,
436: jobAttributes, pageAttributes);
437:
438: if (printJob.printDialog() == false) {
439: printJob = null;
440: }
441:
442: return printJob;
443: }
444:
445: public native void beep();
446:
447: public Clipboard getSystemClipboard() {
448: SecurityManager security = System.getSecurityManager();
449: if (security != null) {
450: security.checkSystemClipboardAccess();
451: }
452: synchronized (this ) {
453: if (clipboard == null) {
454: clipboard = new X11Clipboard("System", "CLIPBOARD");
455: }
456: }
457: return clipboard;
458: }
459:
460: public Clipboard getSystemSelection() {
461: SecurityManager security = System.getSecurityManager();
462: if (security != null) {
463: security.checkSystemClipboardAccess();
464: }
465: synchronized (this ) {
466: if (selection == null) {
467: selection = new X11Clipboard("Selection", "PRIMARY");
468: }
469: }
470: return selection;
471: }
472:
473: public boolean getLockingKeyState(int key) {
474: if (!(key == KeyEvent.VK_CAPS_LOCK
475: || key == KeyEvent.VK_NUM_LOCK
476: || key == KeyEvent.VK_SCROLL_LOCK || key == KeyEvent.VK_KANA_LOCK)) {
477: throw new IllegalArgumentException(
478: "invalid key for Toolkit.getLockingKeyState");
479: }
480: return getLockingKeyStateNative(key);
481: }
482:
483: public native boolean getLockingKeyStateNative(int key);
484:
485: public native void loadSystemColors(int[] systemColors);
486:
487: /**
488: * Give native peers the ability to query the native container
489: * given a native component (e.g. the direct parent may be lightweight).
490: */
491: public static Container getNativeContainer(Component c) {
492: return Toolkit.getNativeContainer(c);
493: }
494:
495: protected static final Object targetToPeer(Object target) {
496: return SunToolkit.targetToPeer(target);
497: }
498:
499: protected static final void targetDisposedPeer(Object target,
500: Object peer) {
501: SunToolkit.targetDisposedPeer(target, peer);
502: }
503:
504: public DragSourceContextPeer createDragSourceContextPeer(
505: DragGestureEvent dge) throws InvalidDnDOperationException {
506: if (MToolkit.useMotifDnD()) {
507: return MDragSourceContextPeer
508: .createDragSourceContextPeer(dge);
509: } else {
510: return X11DragSourceContextPeer
511: .createDragSourceContextPeer(dge);
512: }
513: }
514:
515: public <T extends DragGestureRecognizer> T createDragGestureRecognizer(
516: Class<T> abstractRecognizerClass, DragSource ds,
517: Component c, int srcActions, DragGestureListener dgl) {
518: if (MouseDragGestureRecognizer.class
519: .equals(abstractRecognizerClass))
520: return (T) new MMouseDragGestureRecognizer(ds, c,
521: srcActions, dgl);
522: else
523: return null;
524: }
525:
526: /**
527: * Returns a new input method adapter descriptor for native input methods.
528: */
529: public InputMethodDescriptor getInputMethodAdapterDescriptor()
530: throws AWTException {
531: return new MInputMethodDescriptor();
532: }
533:
534: /**
535: * Returns a style map for the input method highlight.
536: */
537: public Map mapInputMethodHighlight(InputMethodHighlight highlight) {
538: return MInputMethod.mapInputMethodHighlight(highlight);
539: }
540:
541: /**
542: * Returns a new custom cursor.
543: */
544: public Cursor createCustomCursor(Image cursor, Point hotSpot,
545: String name) throws IndexOutOfBoundsException {
546: return new MCustomCursor(cursor, hotSpot, name);
547: }
548:
549: /**
550: * Returns the supported cursor size
551: */
552: public Dimension getBestCursorSize(int preferredWidth,
553: int preferredHeight) {
554: return MCustomCursor
555: .getBestCursorSize(java.lang.Math
556: .max(1, preferredWidth), java.lang.Math.max(1,
557: preferredHeight));
558: }
559:
560: public int getMaximumCursorColors() {
561: return 2; // Black and white.
562: }
563:
564: private final static String prefix = "DnD.Cursor.";
565: private final static String postfix = ".32x32";
566: private static final String dndPrefix = "DnD.";
567:
568: protected Object lazilyLoadDesktopProperty(String name) {
569: if (name.startsWith(prefix)) {
570: String cursorName = name.substring(prefix.length(), name
571: .length())
572: + postfix;
573:
574: try {
575: return Cursor.getSystemCustomCursor(cursorName);
576: } catch (AWTException awte) {
577: System.err.println("cannot load system cursor: "
578: + cursorName);
579:
580: return null;
581: }
582: }
583:
584: if (name.equals("awt.dynamicLayoutSupported")) {
585: return lazilyLoadDynamicLayoutSupportedProperty(name);
586: }
587:
588: if (!loadedXSettings
589: && (name.startsWith("gnome.")
590: || name.equals(SunToolkit.DESKTOPFONTHINTS) || name
591: .startsWith(dndPrefix))) {
592: loadedXSettings = true;
593: if (!GraphicsEnvironment.isHeadless()) {
594: loadXSettings();
595: desktopProperties.put(SunToolkit.DESKTOPFONTHINTS,
596: SunToolkit.getDesktopFontHints());
597: return desktopProperties.get(name);
598: }
599: }
600:
601: return super .lazilyLoadDesktopProperty(name);
602: }
603:
604: /*
605: * Called from lazilyLoadDesktopProperty because we may not know if
606: * the user has quit the previous window manager and started another.
607: */
608: protected Boolean lazilyLoadDynamicLayoutSupportedProperty(
609: String name) {
610: boolean nativeDynamic = isDynamicLayoutSupportedNative();
611:
612: if (dbg.on) {
613: dbg
614: .print("In MTK.lazilyLoadDynamicLayoutSupportedProperty()"
615: + " nativeDynamic == " + nativeDynamic);
616: }
617:
618: return Boolean.valueOf(nativeDynamic);
619: }
620:
621: private native int getMulticlickTime();
622:
623: private native int getNumMouseButtons();
624:
625: protected void initializeDesktopProperties() {
626: desktopProperties.put("DnD.Autoscroll.initialDelay", Integer
627: .valueOf(50));
628: desktopProperties.put("DnD.Autoscroll.interval", Integer
629: .valueOf(50));
630: desktopProperties.put("DnD.Autoscroll.cursorHysteresis",
631: Integer.valueOf(5));
632:
633: /* As of 1.4, no wheel mice are supported on Solaris
634: * however, they are on Linux, and there isn't a way to detect them,
635: * so we leave this property unset to indicate we're not sure if there's
636: * a wheel mouse or not.
637: */
638: //desktopProperties.put("awt.wheelMousePresent", Boolean.valueOf(false));
639: // We don't want to call getMultilclickTime() if we're headless
640: if (!GraphicsEnvironment.isHeadless()) {
641: desktopProperties.put("awt.multiClickInterval", Integer
642: .valueOf(getMulticlickTime()));
643: desktopProperties.put("awt.mouse.numButtons", Integer
644: .valueOf(getNumMouseButtons()));
645: }
646: }
647:
648: public RobotPeer createRobot(Robot target, GraphicsDevice screen) {
649: /* 'target' is unused for now... */
650: return new MRobotPeer(screen.getDefaultConfiguration());
651: }
652:
653: static boolean useMotifDnD() {
654: return motifdnd;
655: }
656:
657: //
658: // The following support Gnome's equivalent of desktop properties.
659: // A writeup of this can be found at:
660: // http://www.freedesktop.org/standards/xsettings/xsettings.html
661: //
662:
663: /**
664: * Triggers a callback to parseXSettings with the x settings values
665: * from the window server. Note that this will NOT call
666: * parseXSettings if we are not running on a GNOME desktop.
667: */
668: private native void loadXSettings();
669:
670: /**
671: * Callback from the native side indicating some, or all, of the
672: * desktop properties have changed and need to be reloaded.
673: * <code>data</code> is the byte array directly from the x server and
674: * may be in little endian format.
675: * <p>
676: * NB: This could be called from any thread if triggered by
677: * <code>loadXSettings</code>. It is called from the toolkit
678: * thread if triggered by an XSETTINGS change.
679: */
680: private void parseXSettings(int screen_XXX_ignored, byte[] data) {
681: // XXX: notyet: map screen -> per screen XSettings object
682: // for now native code only calls us for default screen
683: // see awt_MToolkit.c awt_xsettings_update().
684: if (xs == null) {
685: xs = new XSettings();
686: }
687:
688: Map updatedSettings = xs.update(data);
689: if (updatedSettings == null || updatedSettings.isEmpty()) {
690: return;
691: }
692:
693: Iterator i = updatedSettings.entrySet().iterator();
694: while (i.hasNext()) {
695: Map.Entry e = (Map.Entry) i.next();
696: String name = (String) e.getKey();
697:
698: name = "gnome." + name;
699: setDesktopProperty(name, e.getValue());
700:
701: // XXX: we probably want to do something smarter. In
702: // particular, "Net" properties are of interest to the
703: // "core" AWT itself. E.g.
704: //
705: // Net/DndDragThreshold -> ???
706: // Net/DoubleClickTime -> awt.multiClickInterval
707: }
708:
709: setDesktopProperty(SunToolkit.DESKTOPFONTHINTS, SunToolkit
710: .getDesktopFontHints());
711:
712: Integer dragThreshold = null;
713: synchronized (this ) {
714: dragThreshold = (Integer) desktopProperties
715: .get("gnome.Net/DndDragThreshold");
716: }
717: if (dragThreshold != null) {
718: setDesktopProperty("DnD.gestureMotionThreshold",
719: dragThreshold);
720: }
721: }
722:
723: protected boolean needsXEmbedImpl() {
724: return true;
725: }
726:
727: public boolean isModalityTypeSupported(
728: Dialog.ModalityType modalityType) {
729: return (modalityType == Dialog.ModalityType.MODELESS)
730: || (modalityType == Dialog.ModalityType.APPLICATION_MODAL);
731: }
732:
733: public boolean isModalExclusionTypeSupported(
734: Dialog.ModalExclusionType exclusionType) {
735: return (exclusionType == Dialog.ModalExclusionType.NO_EXCLUDE);
736: }
737:
738: private native boolean isSyncUpdated();
739:
740: private native boolean isSyncFailed();
741:
742: private native int getEventNumber();
743:
744: private native void updateSyncSelection();
745:
746: private static final long WORKAROUND_SLEEP = 100;
747:
748: /**
749: * @inheritDoc
750: */
751: protected boolean syncNativeQueue(final long timeout) {
752: awtLock();
753: try {
754: long event_number = getEventNumber();
755: updateSyncSelection();
756:
757: // Wait for selection notify for oops on win
758: long start = System.currentTimeMillis();
759: while (!isSyncUpdated() && !isSyncFailed()) {
760: try {
761: awtLockWait(timeout);
762: } catch (InterruptedException e) {
763: throw new RuntimeException(e);
764: }
765: // This "while" is a protection from spurious
766: // wake-ups. However, we shouldn't wait for too long
767: if (((System.currentTimeMillis() - start) > timeout)
768: && (timeout >= 0)) {
769: throw new OperationTimedOut();
770: }
771: }
772: if (isSyncFailed() && getEventNumber() - event_number == 1) {
773: awtUnlock();
774: try {
775: Thread.sleep(WORKAROUND_SLEEP);
776: } catch (InterruptedException ie) {
777: throw new RuntimeException(ie);
778: } finally {
779: awtLock();
780: }
781: }
782: return getEventNumber() - event_number > 2;
783: } finally {
784: awtUnlock();
785: }
786: }
787:
788: public void grab(Window w) {
789: WindowPeer peer = (WindowPeer) w.getPeer();
790: if (peer != null) {
791: nativeGrab(peer);
792: }
793: }
794:
795: public void ungrab(Window w) {
796: WindowPeer peer = (WindowPeer) w.getPeer();
797: if (peer != null) {
798: nativeUnGrab(peer);
799: }
800: }
801:
802: private native void nativeGrab(WindowPeer peer);
803:
804: private native void nativeUnGrab(WindowPeer peer);
805:
806: public boolean isDesktopSupported() {
807: return false;
808: }
809:
810: public DesktopPeer createDesktopPeer(Desktop target)
811: throws HeadlessException {
812: throw new UnsupportedOperationException();
813: }
814:
815: public final static int UNDETERMINED_WM = 1, NO_WM = 2,
816: OTHER_WM = 3, OPENLOOK_WM = 4, MOTIF_WM = 5, CDE_WM = 6,
817: ENLIGHTEN_WM = 7, KDE2_WM = 8, SAWFISH_WM = 9, ICE_WM = 10,
818: METACITY_WM = 11, COMPIZ_WM = 12, LG3D_WM = 13;
819:
820: public static int getWMID() {
821: String wmName = getWMName();
822:
823: if ("NO_WM".equals(wmName)) {
824: return NO_WM;
825: } else if ("OTHER_WM".equals(wmName)) {
826: return OTHER_WM;
827: } else if ("ENLIGHTEN_WM".equals(wmName)) {
828: return ENLIGHTEN_WM;
829: } else if ("KDE2_WM".equals(wmName)) {
830: return KDE2_WM;
831: } else if ("SAWFISH_WM".equals(wmName)) {
832: return SAWFISH_WM;
833: } else if ("ICE_WM".equals(wmName)) {
834: return ICE_WM;
835: } else if ("METACITY_WM".equals(wmName)) {
836: return METACITY_WM;
837: } else if ("OPENLOOK_WM".equals(wmName)) {
838: return OPENLOOK_WM;
839: } else if ("MOTIF_WM".equals(wmName)) {
840: return MOTIF_WM;
841: } else if ("CDE_WM".equals(wmName)) {
842: return CDE_WM;
843: } else if ("COMPIZ_WM".equals(wmName)) {
844: return COMPIZ_WM;
845: } else if ("LG3D_WM".equals(wmName)) {
846: return LG3D_WM;
847: }
848: return UNDETERMINED_WM;
849: }
850:
851: private static native String getWMName();
852:
853: } // class MToolkit
|