001: /*
002: * Copyright 2003-2006 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.X11;
027:
028: import java.util.ArrayList;
029: import java.util.Collections;
030: import java.util.Enumeration;
031: import java.util.HashMap;
032: import java.util.HashSet;
033: import java.util.Hashtable;
034: import java.util.Iterator;
035: import java.util.List;
036: import java.util.logging.*;
037:
038: import java.awt.Point;
039:
040: import sun.awt.dnd.SunDropTargetContextPeer;
041: import sun.awt.dnd.SunDropTargetEvent;
042:
043: /**
044: * The class responsible for registration/deregistration of drop sites.
045: *
046: * @since 1.5
047: */
048: final class XDropTargetRegistry {
049: private static final Logger logger = Logger
050: .getLogger("sun.awt.X11.xembed.xdnd.XDropTargetRegistry");
051:
052: private static final long DELAYED_REGISTRATION_PERIOD = 200;
053:
054: private static final XDropTargetRegistry theInstance = new XDropTargetRegistry();
055:
056: private final HashMap<Long, Runnable> delayedRegistrationMap = new HashMap<Long, Runnable>();
057:
058: private XDropTargetRegistry() {
059: }
060:
061: static XDropTargetRegistry getRegistry() {
062: return theInstance;
063: }
064:
065: /**
066: * Returns the XID of the topmost window with WM_STATE set in the ancestor
067: * heirarchy of the specified window or 0 if none found.
068: */
069: private long getToplevelWindow(long window) {
070: XBaseWindow candWindow = XToolkit.windowToXWindow(window);
071: if (candWindow != null) {
072: XWindowPeer toplevel = candWindow.getToplevelXWindow();
073: if (toplevel != null
074: && !(toplevel instanceof XEmbeddedFramePeer)) {
075: return toplevel.getWindow();
076: }
077: }
078:
079: /* Traverse the ancestor tree from window up to the root and find
080: the top-level client window nearest to the root. */
081: do {
082: if (XlibUtil.isTrueToplevelWindow(window)) {
083: return window;
084: }
085:
086: window = XlibUtil.getParentWindow(window);
087:
088: } while (window != 0);
089:
090: return window;
091: }
092:
093: static final long getDnDProxyWindow() {
094: return XWindow.getXAWTRootWindow().getWindow();
095: }
096:
097: private static final class EmbeddedDropSiteEntry {
098: private final long root;
099: private final long event_mask;
100: private List<XDropTargetProtocol> supportedProtocols;
101: private final HashSet<Long> nonXEmbedClientSites = new HashSet<Long>();
102: private final List<Long> sites = new ArrayList<Long>();
103:
104: public EmbeddedDropSiteEntry(long root, long event_mask,
105: List<XDropTargetProtocol> supportedProtocols) {
106: if (supportedProtocols == null) {
107: throw new NullPointerException(
108: "Null supportedProtocols");
109: }
110: this .root = root;
111: this .event_mask = event_mask;
112: this .supportedProtocols = supportedProtocols;
113: }
114:
115: public long getRoot() {
116: return root;
117: }
118:
119: public long getEventMask() {
120: return event_mask;
121: }
122:
123: public boolean hasNonXEmbedClientSites() {
124: return !nonXEmbedClientSites.isEmpty();
125: }
126:
127: public synchronized void addSite(long window,
128: boolean isXEmbedClient) {
129: Long lWindow = Long.valueOf(window);
130: if (!sites.contains(lWindow)) {
131: sites.add(lWindow);
132: }
133: if (!isXEmbedClient) {
134: nonXEmbedClientSites.add(lWindow);
135: }
136: }
137:
138: public synchronized void removeSite(long window) {
139: Long lWindow = Long.valueOf(window);
140: sites.remove(lWindow);
141: nonXEmbedClientSites.remove(lWindow);
142: }
143:
144: public void setSupportedProtocols(List<XDropTargetProtocol> list) {
145: supportedProtocols = list;
146: }
147:
148: public List<XDropTargetProtocol> getSupportedProtocols() {
149: return supportedProtocols;
150: }
151:
152: public boolean hasSites() {
153: return !sites.isEmpty();
154: }
155:
156: public long[] getSites() {
157: long[] ret = new long[sites.size()];
158: Iterator iter = sites.iterator();
159: int index = 0;
160: while (iter.hasNext()) {
161: Long l = (Long) iter.next();
162: ret[index++] = l.longValue();
163: }
164: return ret;
165: }
166:
167: public long getSite(int x, int y) {
168: assert XToolkit.isAWTLockHeldByCurrentThread();
169:
170: Iterator<Long> iter = sites.iterator();
171: while (iter.hasNext()) {
172: Long l = iter.next();
173: long window = l.longValue();
174:
175: Point p = XBaseWindow.toOtherWindow(getRoot(), window,
176: x, y);
177:
178: if (p == null) {
179: continue;
180: }
181:
182: int dest_x = p.x;
183: int dest_y = p.y;
184: if (dest_x >= 0 && dest_y >= 0) {
185: XWindowAttributes wattr = new XWindowAttributes();
186: try {
187: XToolkit
188: .WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
189: int status = XlibWrapper.XGetWindowAttributes(
190: XToolkit.getDisplay(), window,
191: wattr.pData);
192: XToolkit.RESTORE_XERROR_HANDLER();
193:
194: if (status == 0
195: || (XToolkit.saved_error != null && XToolkit.saved_error
196: .get_error_code() != XlibWrapper.Success)) {
197: continue;
198: }
199:
200: if (wattr.get_map_state() != XlibWrapper.IsUnmapped
201: && dest_x < wattr.get_width()
202: && dest_y < wattr.get_height()) {
203: return window;
204: }
205: } finally {
206: wattr.dispose();
207: }
208: }
209: }
210: return 0;
211: }
212: }
213:
214: private final HashMap<Long, EmbeddedDropSiteEntry> embeddedDropSiteRegistry = new HashMap<Long, EmbeddedDropSiteEntry>();
215:
216: private EmbeddedDropSiteEntry registerEmbedderDropSite(long embedder) {
217: assert XToolkit.isAWTLockHeldByCurrentThread();
218:
219: Iterator dropTargetProtocols = XDragAndDropProtocols
220: .getDropTargetProtocols();
221: // The list of protocols supported by the embedder.
222: List<XDropTargetProtocol> embedderProtocols = new ArrayList();
223:
224: while (dropTargetProtocols.hasNext()) {
225: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
226: .next();
227: if (dropTargetProtocol.isProtocolSupported(embedder)) {
228: embedderProtocols.add(dropTargetProtocol);
229: }
230: }
231:
232: embedderProtocols = Collections
233: .unmodifiableList(embedderProtocols);
234:
235: /* Grab server, since we are working with the window that belongs to
236: another client. */
237: XlibWrapper.XGrabServer(XToolkit.getDisplay());
238: try {
239: long root = 0;
240: long event_mask = 0;
241: XWindowAttributes wattr = new XWindowAttributes();
242: try {
243: XToolkit
244: .WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
245: int status = XlibWrapper.XGetWindowAttributes(XToolkit
246: .getDisplay(), embedder, wattr.pData);
247: XToolkit.RESTORE_XERROR_HANDLER();
248:
249: if (status == 0
250: || (XToolkit.saved_error != null && XToolkit.saved_error
251: .get_error_code() != XlibWrapper.Success)) {
252: throw new XException("XGetWindowAttributes failed");
253: }
254:
255: event_mask = wattr.get_your_event_mask();
256: root = wattr.get_root();
257: } finally {
258: wattr.dispose();
259: }
260:
261: if ((event_mask & XlibWrapper.PropertyChangeMask) == 0) {
262: XToolkit
263: .WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
264: XlibWrapper.XSelectInput(XToolkit.getDisplay(),
265: embedder, event_mask
266: | XlibWrapper.PropertyChangeMask);
267: XToolkit.RESTORE_XERROR_HANDLER();
268:
269: if (XToolkit.saved_error != null
270: && XToolkit.saved_error.get_error_code() != XlibWrapper.Success) {
271: throw new XException("XSelectInput failed");
272: }
273: }
274:
275: return new EmbeddedDropSiteEntry(root, event_mask,
276: embedderProtocols);
277: } finally {
278: XlibWrapper.XUngrabServer(XToolkit.getDisplay());
279: }
280: }
281:
282: private static final boolean XEMBED_PROTOCOLS = true;
283: private static final boolean NON_XEMBED_PROTOCOLS = false;
284:
285: private void registerProtocols(long embedder, boolean protocols,
286: List<XDropTargetProtocol> supportedProtocols) {
287: Iterator dropTargetProtocols = null;
288:
289: /*
290: * By default, we register a drop site that supports all dnd
291: * protocols. This approach is not appropriate in plugin
292: * scenario if the browser supports Motif DnD and doesn't support
293: * XDnD. If we forcibly set XdndAware on the browser toplevel, any drag
294: * source that supports both protocols and prefers XDnD will be unable
295: * to drop anything on the browser.
296: * The solution for this problem is not to register XDnD drop site
297: * if the browser supports only Motif DnD.
298: * In general, if the browser already supports some protocols, we
299: * register the embedded drop site only for those protocols. Otherwise
300: * we register the embedded drop site for all protocols.
301: */
302: if (!supportedProtocols.isEmpty()) {
303: dropTargetProtocols = supportedProtocols.iterator();
304: } else {
305: dropTargetProtocols = XDragAndDropProtocols
306: .getDropTargetProtocols();
307: }
308:
309: /* Grab server, since we are working with the window that belongs to
310: another client. */
311: XlibWrapper.XGrabServer(XToolkit.getDisplay());
312: try {
313: while (dropTargetProtocols.hasNext()) {
314: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
315: .next();
316: if ((protocols == XEMBED_PROTOCOLS) == dropTargetProtocol
317: .isXEmbedSupported()) {
318: dropTargetProtocol
319: .registerEmbedderDropSite(embedder);
320: }
321: }
322: } finally {
323: XlibWrapper.XUngrabServer(XToolkit.getDisplay());
324: }
325: }
326:
327: public void updateEmbedderDropSite(long embedder) {
328: XBaseWindow xbaseWindow = XToolkit.windowToXWindow(embedder);
329: // No need to update our own drop sites.
330: if (xbaseWindow != null) {
331: return;
332: }
333:
334: assert XToolkit.isAWTLockHeldByCurrentThread();
335:
336: Iterator dropTargetProtocols = XDragAndDropProtocols
337: .getDropTargetProtocols();
338: // The list of protocols supported by the embedder.
339: List<XDropTargetProtocol> embedderProtocols = new ArrayList();
340:
341: while (dropTargetProtocols.hasNext()) {
342: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
343: .next();
344: if (dropTargetProtocol.isProtocolSupported(embedder)) {
345: embedderProtocols.add(dropTargetProtocol);
346: }
347: }
348:
349: embedderProtocols = Collections
350: .unmodifiableList(embedderProtocols);
351:
352: Long lToplevel = new Long(embedder);
353: boolean isXEmbedServer = false;
354: synchronized (this ) {
355: EmbeddedDropSiteEntry entry = (EmbeddedDropSiteEntry) embeddedDropSiteRegistry
356: .get(lToplevel);
357: if (entry == null) {
358: return;
359: }
360: entry.setSupportedProtocols(embedderProtocols);
361: isXEmbedServer = !entry.hasNonXEmbedClientSites();
362: }
363:
364: /*
365: * By default, we register a drop site that supports all dnd
366: * protocols. This approach is not appropriate in plugin
367: * scenario if the browser supports Motif DnD and doesn't support
368: * XDnD. If we forcibly set XdndAware on the browser toplevel, any drag
369: * source that supports both protocols and prefers XDnD will be unable
370: * to drop anything on the browser.
371: * The solution for this problem is not to register XDnD drop site
372: * if the browser supports only Motif DnD.
373: * In general, if the browser already supports some protocols, we
374: * register the embedded drop site only for those protocols. Otherwise
375: * we register the embedded drop site for all protocols.
376: */
377: if (!embedderProtocols.isEmpty()) {
378: dropTargetProtocols = embedderProtocols.iterator();
379: } else {
380: dropTargetProtocols = XDragAndDropProtocols
381: .getDropTargetProtocols();
382: }
383:
384: /* Grab server, since we are working with the window that belongs to
385: another client. */
386: XlibWrapper.XGrabServer(XToolkit.getDisplay());
387: try {
388: while (dropTargetProtocols.hasNext()) {
389: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
390: .next();
391: if (!isXEmbedServer
392: || !dropTargetProtocol.isXEmbedSupported()) {
393: dropTargetProtocol
394: .registerEmbedderDropSite(embedder);
395: }
396: }
397: } finally {
398: XlibWrapper.XUngrabServer(XToolkit.getDisplay());
399: }
400: }
401:
402: private void unregisterEmbedderDropSite(long embedder,
403: EmbeddedDropSiteEntry entry) {
404: assert XToolkit.isAWTLockHeldByCurrentThread();
405:
406: Iterator dropTargetProtocols = XDragAndDropProtocols
407: .getDropTargetProtocols();
408:
409: /* Grab server, since we are working with the window that belongs to
410: another client. */
411: XlibWrapper.XGrabServer(XToolkit.getDisplay());
412: try {
413: while (dropTargetProtocols.hasNext()) {
414: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
415: .next();
416: dropTargetProtocol.unregisterEmbedderDropSite(embedder);
417: }
418:
419: long event_mask = entry.getEventMask();
420:
421: /* Restore the original event mask for the embedder. */
422: if ((event_mask & XlibWrapper.PropertyChangeMask) == 0) {
423: XToolkit
424: .WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
425: XlibWrapper.XSelectInput(XToolkit.getDisplay(),
426: embedder, event_mask);
427: XToolkit.RESTORE_XERROR_HANDLER();
428:
429: if (XToolkit.saved_error != null
430: && XToolkit.saved_error.get_error_code() != XlibWrapper.Success) {
431: throw new XException("XSelectInput failed");
432: }
433: }
434: } finally {
435: XlibWrapper.XUngrabServer(XToolkit.getDisplay());
436: }
437: }
438:
439: private void registerEmbeddedDropSite(long toplevel, long window) {
440: XBaseWindow xBaseWindow = XToolkit.windowToXWindow(window);
441: boolean isXEmbedClient = (xBaseWindow instanceof XEmbeddedFramePeer)
442: && ((XEmbeddedFramePeer) xBaseWindow).isXEmbedActive();
443:
444: XEmbedCanvasPeer peer = null;
445: {
446: XBaseWindow xbaseWindow = XToolkit
447: .windowToXWindow(toplevel);
448: if (xbaseWindow != null) {
449: if (xbaseWindow instanceof XEmbedCanvasPeer) {
450: peer = (XEmbedCanvasPeer) xbaseWindow;
451: } else {
452: throw new UnsupportedOperationException();
453: }
454: }
455: }
456:
457: Long lToplevel = Long.valueOf(toplevel);
458: EmbeddedDropSiteEntry entry = null;
459: synchronized (this ) {
460: entry = (EmbeddedDropSiteEntry) embeddedDropSiteRegistry
461: .get(lToplevel);
462: if (entry == null) {
463: if (peer != null) {
464: // Toplevel is an XEmbed server within this VM.
465: // Register an XEmbed drop site.
466: peer.setXEmbedDropTarget();
467: // Create a dummy entry to register the embedded site.
468: entry = new EmbeddedDropSiteEntry(0, 0, Collections
469: .<XDropTargetProtocol> emptyList());
470: } else {
471: // Foreign toplevel.
472: // Select for PropertyNotify events on the toplevel, so that
473: // we can track changes of the properties relevant to DnD
474: // protocols.
475: entry = registerEmbedderDropSite(toplevel);
476: // Register the toplevel with all DnD protocols that are not
477: // supported by XEmbed - actually setup a proxy, so that
478: // all DnD notifications sent to the toplevel are first
479: // routed to us.
480: registerProtocols(toplevel, NON_XEMBED_PROTOCOLS,
481: entry.getSupportedProtocols());
482: }
483: embeddedDropSiteRegistry.put(lToplevel, entry);
484: }
485: }
486:
487: assert entry != null;
488:
489: synchronized (entry) {
490: // For a foreign toplevel.
491: if (peer == null) {
492: if (!isXEmbedClient) {
493: // Since this is not an XEmbed client we can no longer rely
494: // on XEmbed to route DnD notifications even for DnD
495: // protocols that are supported by XEmbed.
496: // We rollback to the XEmbed-unfriendly solution - setup
497: // a proxy, so that all DnD notifications sent to the
498: // toplevel are first routed to us.
499: registerProtocols(toplevel, XEMBED_PROTOCOLS, entry
500: .getSupportedProtocols());
501: } else {
502: Iterator dropTargetProtocols = XDragAndDropProtocols
503: .getDropTargetProtocols();
504:
505: // Register the embedded window as a plain drop site with
506: // all DnD protocols that are supported by XEmbed.
507: while (dropTargetProtocols.hasNext()) {
508: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
509: .next();
510: if (dropTargetProtocol.isXEmbedSupported()) {
511: dropTargetProtocol
512: .registerEmbedderDropSite(window);
513: }
514: }
515: }
516: }
517:
518: entry.addSite(window, isXEmbedClient);
519: }
520: }
521:
522: private void unregisterEmbeddedDropSite(long toplevel, long window) {
523: Long lToplevel = Long.valueOf(toplevel);
524: EmbeddedDropSiteEntry entry = null;
525: synchronized (this ) {
526: entry = (EmbeddedDropSiteEntry) embeddedDropSiteRegistry
527: .get(lToplevel);
528: if (entry == null) {
529: return;
530: }
531: entry.removeSite(window);
532: if (!entry.hasSites()) {
533: embeddedDropSiteRegistry.remove(lToplevel);
534:
535: XBaseWindow xbaseWindow = XToolkit
536: .windowToXWindow(toplevel);
537: if (xbaseWindow != null) {
538: if (xbaseWindow instanceof XEmbedCanvasPeer) {
539: XEmbedCanvasPeer peer = (XEmbedCanvasPeer) xbaseWindow;
540: // Unregister an XEmbed drop site.
541: peer.removeXEmbedDropTarget();
542: } else {
543: throw new UnsupportedOperationException();
544: }
545: } else {
546: unregisterEmbedderDropSite(toplevel, entry);
547: }
548: }
549: }
550: }
551:
552: /*
553: * Returns a drop site that is embedded in the specified embedder window and
554: * contains the point with the specified root coordinates.
555: */
556: public long getEmbeddedDropSite(long embedder, int x, int y) {
557: Long lToplevel = Long.valueOf(embedder);
558: EmbeddedDropSiteEntry entry = (EmbeddedDropSiteEntry) embeddedDropSiteRegistry
559: .get(lToplevel);
560: if (entry == null) {
561: return 0;
562: }
563: return entry.getSite(x, y);
564: }
565:
566: public void registerDropSite(long window) {
567: if (window == 0) {
568: throw new IllegalArgumentException();
569: }
570:
571: XDropTargetEventProcessor.activate();
572:
573: XToolkit.awtLock();
574: try {
575: long toplevel = getToplevelWindow(window);
576:
577: /*
578: * No window with WM_STATE property is found.
579: * Since the window can be a plugin window reparented to the browser
580: * toplevel, we cannot determine which window will eventually have
581: * WM_STATE property set. So we schedule a timer callback that will
582: * periodically attempt to find an ancestor with WM_STATE and
583: * register the drop site appropriately.
584: */
585: if (toplevel == 0) {
586: addDelayedRegistrationEntry(window);
587: return;
588: }
589:
590: if (toplevel == window) {
591: Iterator dropTargetProtocols = XDragAndDropProtocols
592: .getDropTargetProtocols();
593:
594: while (dropTargetProtocols.hasNext()) {
595: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
596: .next();
597: dropTargetProtocol.registerDropTarget(toplevel);
598: }
599: } else {
600: registerEmbeddedDropSite(toplevel, window);
601: }
602: } finally {
603: XToolkit.awtUnlock();
604: }
605: }
606:
607: public void unregisterDropSite(long window) {
608: if (window == 0) {
609: throw new IllegalArgumentException();
610: }
611:
612: XToolkit.awtLock();
613: try {
614: long toplevel = getToplevelWindow(window);
615:
616: if (toplevel == window) {
617: Iterator dropProtocols = XDragAndDropProtocols
618: .getDropTargetProtocols();
619:
620: removeDelayedRegistrationEntry(window);
621:
622: while (dropProtocols.hasNext()) {
623: XDropTargetProtocol dropProtocol = (XDropTargetProtocol) dropProtocols
624: .next();
625: dropProtocol.unregisterDropTarget(window);
626: }
627: } else {
628: unregisterEmbeddedDropSite(toplevel, window);
629: }
630: } finally {
631: XToolkit.awtUnlock();
632: }
633: }
634:
635: public void registerXEmbedClient(long canvasWindow,
636: long clientWindow) {
637: // If the client has an associated XDnD drop site, add a drop target
638: // to the XEmbedCanvasPeer's target to route drag notifications to the
639: // client.
640:
641: XDragSourceProtocol xdndDragProtocol = XDragAndDropProtocols
642: .getDragSourceProtocol(XDragAndDropProtocols.XDnD);
643: XDragSourceProtocol.TargetWindowInfo info = xdndDragProtocol
644: .getTargetWindowInfo(clientWindow);
645: if (info != null
646: && info.getProtocolVersion() >= XDnDConstants.XDND_MIN_PROTOCOL_VERSION) {
647:
648: if (logger.isLoggable(Level.FINE)) {
649: logger
650: .fine(" XEmbed drop site will be registered for "
651: + Long.toHexString(clientWindow));
652: }
653: registerEmbeddedDropSite(canvasWindow, clientWindow);
654:
655: Iterator dropTargetProtocols = XDragAndDropProtocols
656: .getDropTargetProtocols();
657:
658: while (dropTargetProtocols.hasNext()) {
659: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
660: .next();
661: dropTargetProtocol
662: .registerEmbeddedDropSite(clientWindow);
663: }
664:
665: if (logger.isLoggable(Level.FINE)) {
666: logger
667: .fine(" XEmbed drop site has been registered for "
668: + Long.toHexString(clientWindow));
669: }
670: }
671: }
672:
673: public void unregisterXEmbedClient(long canvasWindow,
674: long clientWindow) {
675: if (logger.isLoggable(Level.FINE)) {
676: logger
677: .fine(" XEmbed drop site will be unregistered for "
678: + Long.toHexString(clientWindow));
679: }
680: Iterator dropTargetProtocols = XDragAndDropProtocols
681: .getDropTargetProtocols();
682:
683: while (dropTargetProtocols.hasNext()) {
684: XDropTargetProtocol dropTargetProtocol = (XDropTargetProtocol) dropTargetProtocols
685: .next();
686: dropTargetProtocol.unregisterEmbeddedDropSite(clientWindow);
687: }
688:
689: unregisterEmbeddedDropSite(canvasWindow, clientWindow);
690:
691: if (logger.isLoggable(Level.FINE)) {
692: logger
693: .fine(" XEmbed drop site has beed unregistered for "
694: + Long.toHexString(clientWindow));
695: }
696: }
697:
698: /**************** Delayed drop site registration *******************************/
699:
700: private void addDelayedRegistrationEntry(final long window) {
701: Long lWindow = Long.valueOf(window);
702: Runnable runnable = new Runnable() {
703: public void run() {
704: removeDelayedRegistrationEntry(window);
705: registerDropSite(window);
706: }
707: };
708:
709: XToolkit.awtLock();
710: try {
711: removeDelayedRegistrationEntry(window);
712: delayedRegistrationMap.put(lWindow, runnable);
713: XToolkit.schedule(runnable, DELAYED_REGISTRATION_PERIOD);
714: } finally {
715: XToolkit.awtUnlock();
716: }
717: }
718:
719: private void removeDelayedRegistrationEntry(long window) {
720: Long lWindow = Long.valueOf(window);
721:
722: XToolkit.awtLock();
723: try {
724: Runnable runnable = delayedRegistrationMap.remove(lWindow);
725: if (runnable != null) {
726: XToolkit.remove(runnable);
727: }
728: } finally {
729: XToolkit.awtUnlock();
730: }
731: }
732: /*******************************************************************************/
733: }
|