1 /* 2 * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt.X11; 27 28 import java.util.ArrayList; 29 import java.util.Collections; 30 import java.util.HashMap; 31 import java.util.HashSet; 32 import java.util.Iterator; 33 import java.util.List; 34 import sun.util.logging.PlatformLogger; 35 36 import java.awt.Point; 37 38 39 /** 40 * The class responsible for registration/deregistration of drop sites. 41 * 42 * @since 1.5 43 */ 44 final class XDropTargetRegistry { 45 private static final PlatformLogger logger = 46 PlatformLogger.getLogger("sun.awt.X11.xembed.xdnd.XDropTargetRegistry"); 47 48 private static final long DELAYED_REGISTRATION_PERIOD = 200; 49 50 private static final XDropTargetRegistry theInstance = 51 new XDropTargetRegistry(); 52 53 private final HashMap<Long, Runnable> delayedRegistrationMap = 54 new HashMap<Long, Runnable>(); 55 56 private XDropTargetRegistry() {} 57 58 static XDropTargetRegistry getRegistry() { 59 return theInstance; 60 } 61 62 /** 63 * Returns the XID of the topmost window with WM_STATE set in the ancestor 64 * heirarchy of the specified window or 0 if none found. 65 */ 66 private long getToplevelWindow(long window) { 67 XBaseWindow candWindow = XToolkit.windowToXWindow(window); 68 if (candWindow != null) { 69 XWindowPeer toplevel = candWindow.getToplevelXWindow(); 70 if (toplevel != null && !(toplevel instanceof XEmbeddedFramePeer)) { 71 return toplevel.getWindow(); 72 } 73 } 74 75 /* Traverse the ancestor tree from window up to the root and find 76 the top-level client window nearest to the root. */ 77 do { 78 if (XlibUtil.isTrueToplevelWindow(window)) { 79 return window; 80 } 81 82 window = XlibUtil.getParentWindow(window); 83 84 } while (window != 0); 85 86 return window; 87 } 88 89 static final long getDnDProxyWindow() { 90 return XWindow.getXAWTRootWindow().getWindow(); 91 } 92 93 private static final class EmbeddedDropSiteEntry { 94 private final long root; 95 private final long event_mask; 96 private List<XDropTargetProtocol> supportedProtocols; 97 private final HashSet<Long> nonXEmbedClientSites = new HashSet<Long>(); 98 private final List<Long> sites = new ArrayList<Long>(); 99 100 public EmbeddedDropSiteEntry(long root, long event_mask, 101 List<XDropTargetProtocol> supportedProtocols) { 102 if (supportedProtocols == null) { 103 throw new NullPointerException("Null supportedProtocols"); 104 } 105 this.root = root; 106 this.event_mask = event_mask; 107 this.supportedProtocols = supportedProtocols; 108 } 109 110 public long getRoot() { 111 return root; 112 } 113 public long getEventMask() { 114 return event_mask; 115 } 116 public boolean hasNonXEmbedClientSites() { 117 return !nonXEmbedClientSites.isEmpty(); 118 } 119 public synchronized void addSite(long window, boolean isXEmbedClient) { 120 Long lWindow = Long.valueOf(window); 121 if (!sites.contains(lWindow)) { 122 sites.add(lWindow); 123 } 124 if (!isXEmbedClient) { 125 nonXEmbedClientSites.add(lWindow); 126 } 127 } 128 public synchronized void removeSite(long window) { 129 Long lWindow = Long.valueOf(window); 130 sites.remove(lWindow); 131 nonXEmbedClientSites.remove(lWindow); 132 } 133 public void setSupportedProtocols(List<XDropTargetProtocol> list) { 134 supportedProtocols = list; 135 } 136 public List<XDropTargetProtocol> getSupportedProtocols() { 137 return supportedProtocols; 138 } 139 public boolean hasSites() { 140 return !sites.isEmpty(); 141 } 142 public long[] getSites() { 143 long[] ret = new long[sites.size()]; 144 Iterator iter = sites.iterator(); 145 int index = 0; 146 while (iter.hasNext()) { 147 Long l = (Long)iter.next(); 148 ret[index++] = l.longValue(); 149 } 150 return ret; 151 } 152 public long getSite(int x, int y) { 153 assert XToolkit.isAWTLockHeldByCurrentThread(); 154 155 Iterator<Long> iter = sites.iterator(); 156 while (iter.hasNext()) { 157 Long l = iter.next(); 158 long window = l.longValue(); 159 160 Point p = XBaseWindow.toOtherWindow(getRoot(), window, x, y); 161 162 if (p == null) { 163 continue; 164 } 165 166 int dest_x = p.x; 167 int dest_y = p.y; 168 if (dest_x >= 0 && dest_y >= 0) { 169 XWindowAttributes wattr = new XWindowAttributes(); 170 try { 171 XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 172 int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), 173 window, wattr.pData); 174 XToolkit.RESTORE_XERROR_HANDLER(); 175 176 if (status == 0 || 177 (XToolkit.saved_error != null && 178 XToolkit.saved_error.get_error_code() != XConstants.Success)) { 179 continue; 180 } 181 182 if (wattr.get_map_state() != XConstants.IsUnmapped 183 && dest_x < wattr.get_width() 184 && dest_y < wattr.get_height()) { 185 return window; 186 } 187 } finally { 188 wattr.dispose(); 189 } 190 } 191 } 192 return 0; 193 } 194 } 195 196 private final HashMap<Long, EmbeddedDropSiteEntry> embeddedDropSiteRegistry = 197 new HashMap<Long, EmbeddedDropSiteEntry>(); 198 199 private EmbeddedDropSiteEntry registerEmbedderDropSite(long embedder) { 200 assert XToolkit.isAWTLockHeldByCurrentThread(); 201 202 Iterator dropTargetProtocols = 203 XDragAndDropProtocols.getDropTargetProtocols(); 204 // The list of protocols supported by the embedder. 205 List<XDropTargetProtocol> embedderProtocols = new ArrayList(); 206 207 while (dropTargetProtocols.hasNext()) { 208 XDropTargetProtocol dropTargetProtocol = 209 (XDropTargetProtocol)dropTargetProtocols.next(); 210 if (dropTargetProtocol.isProtocolSupported(embedder)) { 211 embedderProtocols.add(dropTargetProtocol); 212 } 213 } 214 215 embedderProtocols = Collections.unmodifiableList(embedderProtocols); 216 217 /* Grab server, since we are working with the window that belongs to 218 another client. */ 219 XlibWrapper.XGrabServer(XToolkit.getDisplay()); 220 try { 221 long root = 0; 222 long event_mask = 0; 223 XWindowAttributes wattr = new XWindowAttributes(); 224 try { 225 XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 226 int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), 227 embedder, wattr.pData); 228 XToolkit.RESTORE_XERROR_HANDLER(); 229 230 if (status == 0 || 231 (XToolkit.saved_error != null && 232 XToolkit.saved_error.get_error_code() != XConstants.Success)) { 233 throw new XException("XGetWindowAttributes failed"); 234 } 235 236 event_mask = wattr.get_your_event_mask(); 237 root = wattr.get_root(); 238 } finally { 239 wattr.dispose(); 240 } 241 242 if ((event_mask & XConstants.PropertyChangeMask) == 0) { 243 XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 244 XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder, 245 event_mask | XConstants.PropertyChangeMask); 246 XToolkit.RESTORE_XERROR_HANDLER(); 247 248 if (XToolkit.saved_error != null && 249 XToolkit.saved_error.get_error_code() != XConstants.Success) { 250 throw new XException("XSelectInput failed"); 251 } 252 } 253 254 return new EmbeddedDropSiteEntry(root, event_mask, embedderProtocols); 255 } finally { 256 XlibWrapper.XUngrabServer(XToolkit.getDisplay()); 257 } 258 } 259 260 private static final boolean XEMBED_PROTOCOLS = true; 261 private static final boolean NON_XEMBED_PROTOCOLS = false; 262 263 private void registerProtocols(long embedder, boolean protocols, 264 List<XDropTargetProtocol> supportedProtocols) { 265 Iterator dropTargetProtocols = null; 266 267 /* 268 * By default, we register a drop site that supports all dnd 269 * protocols. This approach is not appropriate in plugin 270 * scenario if the browser supports Motif DnD and doesn't support 271 * XDnD. If we forcibly set XdndAware on the browser toplevel, any drag 272 * source that supports both protocols and prefers XDnD will be unable 273 * to drop anything on the browser. 274 * The solution for this problem is not to register XDnD drop site 275 * if the browser supports only Motif DnD. 276 * In general, if the browser already supports some protocols, we 277 * register the embedded drop site only for those protocols. Otherwise 278 * we register the embedded drop site for all protocols. 279 */ 280 if (!supportedProtocols.isEmpty()) { 281 dropTargetProtocols = supportedProtocols.iterator(); 282 } else { 283 dropTargetProtocols = 284 XDragAndDropProtocols.getDropTargetProtocols(); 285 } 286 287 /* Grab server, since we are working with the window that belongs to 288 another client. */ 289 XlibWrapper.XGrabServer(XToolkit.getDisplay()); 290 try { 291 while (dropTargetProtocols.hasNext()) { 292 XDropTargetProtocol dropTargetProtocol = 293 (XDropTargetProtocol)dropTargetProtocols.next(); 294 if ((protocols == XEMBED_PROTOCOLS) == 295 dropTargetProtocol.isXEmbedSupported()) { 296 dropTargetProtocol.registerEmbedderDropSite(embedder); 297 } 298 } 299 } finally { 300 XlibWrapper.XUngrabServer(XToolkit.getDisplay()); 301 } 302 } 303 304 public void updateEmbedderDropSite(long embedder) { 305 XBaseWindow xbaseWindow = XToolkit.windowToXWindow(embedder); 306 // No need to update our own drop sites. 307 if (xbaseWindow != null) { 308 return; 309 } 310 311 assert XToolkit.isAWTLockHeldByCurrentThread(); 312 313 Iterator dropTargetProtocols = 314 XDragAndDropProtocols.getDropTargetProtocols(); 315 // The list of protocols supported by the embedder. 316 List<XDropTargetProtocol> embedderProtocols = new ArrayList(); 317 318 while (dropTargetProtocols.hasNext()) { 319 XDropTargetProtocol dropTargetProtocol = 320 (XDropTargetProtocol)dropTargetProtocols.next(); 321 if (dropTargetProtocol.isProtocolSupported(embedder)) { 322 embedderProtocols.add(dropTargetProtocol); 323 } 324 } 325 326 embedderProtocols = Collections.unmodifiableList(embedderProtocols); 327 328 Long lToplevel = Long.valueOf(embedder); 329 boolean isXEmbedServer = false; 330 synchronized (this) { 331 EmbeddedDropSiteEntry entry = 332 (EmbeddedDropSiteEntry)embeddedDropSiteRegistry.get(lToplevel); 333 if (entry == null) { 334 return; 335 } 336 entry.setSupportedProtocols(embedderProtocols); 337 isXEmbedServer = !entry.hasNonXEmbedClientSites(); 338 } 339 340 /* 341 * By default, we register a drop site that supports all dnd 342 * protocols. This approach is not appropriate in plugin 343 * scenario if the browser supports Motif DnD and doesn't support 344 * XDnD. If we forcibly set XdndAware on the browser toplevel, any drag 345 * source that supports both protocols and prefers XDnD will be unable 346 * to drop anything on the browser. 347 * The solution for this problem is not to register XDnD drop site 348 * if the browser supports only Motif DnD. 349 * In general, if the browser already supports some protocols, we 350 * register the embedded drop site only for those protocols. Otherwise 351 * we register the embedded drop site for all protocols. 352 */ 353 if (!embedderProtocols.isEmpty()) { 354 dropTargetProtocols = embedderProtocols.iterator(); 355 } else { 356 dropTargetProtocols = 357 XDragAndDropProtocols.getDropTargetProtocols(); 358 } 359 360 /* Grab server, since we are working with the window that belongs to 361 another client. */ 362 XlibWrapper.XGrabServer(XToolkit.getDisplay()); 363 try { 364 while (dropTargetProtocols.hasNext()) { 365 XDropTargetProtocol dropTargetProtocol = 366 (XDropTargetProtocol)dropTargetProtocols.next(); 367 if (!isXEmbedServer || !dropTargetProtocol.isXEmbedSupported()) { 368 dropTargetProtocol.registerEmbedderDropSite(embedder); 369 } 370 } 371 } finally { 372 XlibWrapper.XUngrabServer(XToolkit.getDisplay()); 373 } 374 } 375 376 private void unregisterEmbedderDropSite(long embedder, 377 EmbeddedDropSiteEntry entry) { 378 assert XToolkit.isAWTLockHeldByCurrentThread(); 379 380 Iterator dropTargetProtocols = 381 XDragAndDropProtocols.getDropTargetProtocols(); 382 383 /* Grab server, since we are working with the window that belongs to 384 another client. */ 385 XlibWrapper.XGrabServer(XToolkit.getDisplay()); 386 try { 387 while (dropTargetProtocols.hasNext()) { 388 XDropTargetProtocol dropTargetProtocol = 389 (XDropTargetProtocol)dropTargetProtocols.next(); 390 dropTargetProtocol.unregisterEmbedderDropSite(embedder); 391 } 392 393 long event_mask = entry.getEventMask(); 394 395 /* Restore the original event mask for the embedder. */ 396 if ((event_mask & XConstants.PropertyChangeMask) == 0) { 397 XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 398 XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder, 399 event_mask); 400 XToolkit.RESTORE_XERROR_HANDLER(); 401 402 if (XToolkit.saved_error != null && 403 XToolkit.saved_error.get_error_code() != XConstants.Success) { 404 throw new XException("XSelectInput failed"); 405 } 406 } 407 } finally { 408 XlibWrapper.XUngrabServer(XToolkit.getDisplay()); 409 } 410 } 411 412 private void registerEmbeddedDropSite(long toplevel, long window) { 413 XBaseWindow xBaseWindow = XToolkit.windowToXWindow(window); 414 boolean isXEmbedClient = 415 (xBaseWindow instanceof XEmbeddedFramePeer) && 416 ((XEmbeddedFramePeer)xBaseWindow).isXEmbedActive(); 417 418 XEmbedCanvasPeer peer = null; 419 { 420 XBaseWindow xbaseWindow = XToolkit.windowToXWindow(toplevel); 421 if (xbaseWindow != null) { 422 if (xbaseWindow instanceof XEmbedCanvasPeer) { 423 peer = (XEmbedCanvasPeer)xbaseWindow; 424 } else { 425 throw new UnsupportedOperationException(); 426 } 427 } 428 } 429 430 Long lToplevel = Long.valueOf(toplevel); 431 EmbeddedDropSiteEntry entry = null; 432 synchronized (this) { 433 entry = 434 (EmbeddedDropSiteEntry)embeddedDropSiteRegistry.get(lToplevel); 435 if (entry == null) { 436 if (peer != null) { 437 // Toplevel is an XEmbed server within this VM. 438 // Register an XEmbed drop site. 439 peer.setXEmbedDropTarget(); 440 // Create a dummy entry to register the embedded site. 441 entry = new EmbeddedDropSiteEntry(0, 0, 442 Collections.<XDropTargetProtocol>emptyList()); 443 } else { 444 // Foreign toplevel. 445 // Select for PropertyNotify events on the toplevel, so that 446 // we can track changes of the properties relevant to DnD 447 // protocols. 448 entry = registerEmbedderDropSite(toplevel); 449 // Register the toplevel with all DnD protocols that are not 450 // supported by XEmbed - actually setup a proxy, so that 451 // all DnD notifications sent to the toplevel are first 452 // routed to us. 453 registerProtocols(toplevel, NON_XEMBED_PROTOCOLS, 454 entry.getSupportedProtocols()); 455 } 456 embeddedDropSiteRegistry.put(lToplevel, entry); 457 } 458 } 459 460 assert entry != null; 461 462 synchronized (entry) { 463 // For a foreign toplevel. 464 if (peer == null) { 465 if (!isXEmbedClient) { 466 // Since this is not an XEmbed client we can no longer rely 467 // on XEmbed to route DnD notifications even for DnD 468 // protocols that are supported by XEmbed. 469 // We rollback to the XEmbed-unfriendly solution - setup 470 // a proxy, so that all DnD notifications sent to the 471 // toplevel are first routed to us. 472 registerProtocols(toplevel, XEMBED_PROTOCOLS, 473 entry.getSupportedProtocols()); 474 } else { 475 Iterator dropTargetProtocols = 476 XDragAndDropProtocols.getDropTargetProtocols(); 477 478 // Register the embedded window as a plain drop site with 479 // all DnD protocols that are supported by XEmbed. 480 while (dropTargetProtocols.hasNext()) { 481 XDropTargetProtocol dropTargetProtocol = 482 (XDropTargetProtocol)dropTargetProtocols.next(); 483 if (dropTargetProtocol.isXEmbedSupported()) { 484 dropTargetProtocol.registerEmbedderDropSite(window); 485 } 486 } 487 } 488 } 489 490 entry.addSite(window, isXEmbedClient); 491 } 492 } 493 494 private void unregisterEmbeddedDropSite(long toplevel, long window) { 495 Long lToplevel = Long.valueOf(toplevel); 496 EmbeddedDropSiteEntry entry = null; 497 synchronized (this) { 498 entry = 499 (EmbeddedDropSiteEntry)embeddedDropSiteRegistry.get(lToplevel); 500 if (entry == null) { 501 return; 502 } 503 entry.removeSite(window); 504 if (!entry.hasSites()) { 505 embeddedDropSiteRegistry.remove(lToplevel); 506 507 XBaseWindow xbaseWindow = XToolkit.windowToXWindow(toplevel); 508 if (xbaseWindow != null) { 509 if (xbaseWindow instanceof XEmbedCanvasPeer) { 510 XEmbedCanvasPeer peer = (XEmbedCanvasPeer)xbaseWindow; 511 // Unregister an XEmbed drop site. 512 peer.removeXEmbedDropTarget(); 513 } else { 514 throw new UnsupportedOperationException(); 515 } 516 } else { 517 unregisterEmbedderDropSite(toplevel, entry); 518 } 519 } 520 } 521 } 522 523 /* 524 * Returns a drop site that is embedded in the specified embedder window and 525 * contains the point with the specified root coordinates. 526 */ 527 public long getEmbeddedDropSite(long embedder, int x, int y) { 528 Long lToplevel = Long.valueOf(embedder); 529 EmbeddedDropSiteEntry entry = 530 (EmbeddedDropSiteEntry)embeddedDropSiteRegistry.get(lToplevel); 531 if (entry == null) { 532 return 0; 533 } 534 return entry.getSite(x, y); 535 } 536 537 /* 538 * Note: this method should be called under AWT lock. 539 */ 540 public void registerDropSite(long window) { 541 assert XToolkit.isAWTLockHeldByCurrentThread(); 542 543 if (window == 0) { 544 throw new IllegalArgumentException(); 545 } 546 547 XDropTargetEventProcessor.activate(); 548 549 long toplevel = getToplevelWindow(window); 550 551 /* 552 * No window with WM_STATE property is found. 553 * Since the window can be a plugin window reparented to the browser 554 * toplevel, we cannot determine which window will eventually have 555 * WM_STATE property set. So we schedule a timer callback that will 556 * periodically attempt to find an ancestor with WM_STATE and 557 * register the drop site appropriately. 558 */ 559 if (toplevel == 0) { 560 addDelayedRegistrationEntry(window); 561 return; 562 } 563 564 if (toplevel == window) { 565 Iterator dropTargetProtocols = 566 XDragAndDropProtocols.getDropTargetProtocols(); 567 568 while (dropTargetProtocols.hasNext()) { 569 XDropTargetProtocol dropTargetProtocol = 570 (XDropTargetProtocol)dropTargetProtocols.next(); 571 dropTargetProtocol.registerDropTarget(toplevel); 572 } 573 } else { 574 registerEmbeddedDropSite(toplevel, window); 575 } 576 } 577 578 /* 579 * Note: this method should be called under AWT lock. 580 */ 581 public void unregisterDropSite(long window) { 582 assert XToolkit.isAWTLockHeldByCurrentThread(); 583 584 if (window == 0) { 585 throw new IllegalArgumentException(); 586 } 587 588 long toplevel = getToplevelWindow(window); 589 590 if (toplevel == window) { 591 Iterator dropProtocols = 592 XDragAndDropProtocols.getDropTargetProtocols(); 593 594 removeDelayedRegistrationEntry(window); 595 596 while (dropProtocols.hasNext()) { 597 XDropTargetProtocol dropProtocol = (XDropTargetProtocol)dropProtocols.next(); 598 dropProtocol.unregisterDropTarget(window); 599 } 600 } else { 601 unregisterEmbeddedDropSite(toplevel, window); 602 } 603 } 604 605 public void registerXEmbedClient(long canvasWindow, long clientWindow) { 606 // If the client has an associated XDnD drop site, add a drop target 607 // to the XEmbedCanvasPeer's target to route drag notifications to the 608 // client. 609 610 XDragSourceProtocol xdndDragProtocol = 611 XDragAndDropProtocols.getDragSourceProtocol(XDragAndDropProtocols.XDnD); 612 XDragSourceProtocol.TargetWindowInfo info = 613 xdndDragProtocol.getTargetWindowInfo(clientWindow); 614 if (info != null && 615 info.getProtocolVersion() >= XDnDConstants.XDND_MIN_PROTOCOL_VERSION) { 616 617 if (logger.isLoggable(PlatformLogger.FINE)) { 618 logger.fine(" XEmbed drop site will be registered for " + Long.toHexString(clientWindow)); 619 } 620 registerEmbeddedDropSite(canvasWindow, clientWindow); 621 622 Iterator dropTargetProtocols = 623 XDragAndDropProtocols.getDropTargetProtocols(); 624 625 while (dropTargetProtocols.hasNext()) { 626 XDropTargetProtocol dropTargetProtocol = 627 (XDropTargetProtocol)dropTargetProtocols.next(); 628 dropTargetProtocol.registerEmbeddedDropSite(clientWindow); 629 } 630 631 if (logger.isLoggable(PlatformLogger.FINE)) { 632 logger.fine(" XEmbed drop site has been registered for " + Long.toHexString(clientWindow)); 633 } 634 } 635 } 636 637 public void unregisterXEmbedClient(long canvasWindow, long clientWindow) { 638 if (logger.isLoggable(PlatformLogger.FINE)) { 639 logger.fine(" XEmbed drop site will be unregistered for " + Long.toHexString(clientWindow)); 640 } 641 Iterator dropTargetProtocols = 642 XDragAndDropProtocols.getDropTargetProtocols(); 643 644 while (dropTargetProtocols.hasNext()) { 645 XDropTargetProtocol dropTargetProtocol = 646 (XDropTargetProtocol)dropTargetProtocols.next(); 647 dropTargetProtocol.unregisterEmbeddedDropSite(clientWindow); 648 } 649 650 unregisterEmbeddedDropSite(canvasWindow, clientWindow); 651 652 if (logger.isLoggable(PlatformLogger.FINE)) { 653 logger.fine(" XEmbed drop site has beed unregistered for " + Long.toHexString(clientWindow)); 654 } 655 } 656 657 /**************** Delayed drop site registration *******************************/ 658 659 private void addDelayedRegistrationEntry(final long window) { 660 Long lWindow = Long.valueOf(window); 661 Runnable runnable = new Runnable() { 662 public void run() { 663 removeDelayedRegistrationEntry(window); 664 registerDropSite(window); 665 } 666 }; 667 668 XToolkit.awtLock(); 669 try { 670 removeDelayedRegistrationEntry(window); 671 delayedRegistrationMap.put(lWindow, runnable); 672 XToolkit.schedule(runnable, DELAYED_REGISTRATION_PERIOD); 673 } finally { 674 XToolkit.awtUnlock(); 675 } 676 } 677 678 private void removeDelayedRegistrationEntry(long window) { 679 Long lWindow = Long.valueOf(window); 680 681 XToolkit.awtLock(); 682 try { 683 Runnable runnable = delayedRegistrationMap.remove(lWindow); 684 if (runnable != null) { 685 XToolkit.remove(runnable); 686 } 687 } finally { 688 XToolkit.awtUnlock(); 689 } 690 } 691 /*******************************************************************************/ 692 }