1 /* 2 * Copyright (c) 2003, 2014, 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 * hierarchy 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 XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 172 int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), 173 window, wattr.pData); 174 XErrorHandlerUtil.RESTORE_XERROR_HANDLER(); 175 176 if ((status == 0) || 177 ((XErrorHandlerUtil.saved_error != null) && 178 (XErrorHandlerUtil.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 XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 226 int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), 227 embedder, wattr.pData); 228 XErrorHandlerUtil.RESTORE_XERROR_HANDLER(); 229 230 if ((status == 0) || 231 ((XErrorHandlerUtil.saved_error != null) && 232 (XErrorHandlerUtil.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 XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 244 XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder, 245 event_mask | XConstants.PropertyChangeMask); 246 XErrorHandlerUtil.RESTORE_XERROR_HANDLER(); 247 248 if ((XErrorHandlerUtil.saved_error != null) && 249 (XErrorHandlerUtil.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 = embeddedDropSiteRegistry.get(lToplevel); 332 if (entry == null) { 333 return; 334 } 335 entry.setSupportedProtocols(embedderProtocols); 336 isXEmbedServer = !entry.hasNonXEmbedClientSites(); 337 } 338 339 /* 340 * By default, we register a drop site that supports all dnd 341 * protocols. This approach is not appropriate in plugin 342 * scenario if the browser supports Motif DnD and doesn't support 343 * XDnD. If we forcibly set XdndAware on the browser toplevel, any drag 344 * source that supports both protocols and prefers XDnD will be unable 345 * to drop anything on the browser. 346 * The solution for this problem is not to register XDnD drop site 347 * if the browser supports only Motif DnD. 348 * In general, if the browser already supports some protocols, we 349 * register the embedded drop site only for those protocols. Otherwise 350 * we register the embedded drop site for all protocols. 351 */ 352 if (!embedderProtocols.isEmpty()) { 353 dropTargetProtocols = embedderProtocols.iterator(); 354 } else { 355 dropTargetProtocols = 356 XDragAndDropProtocols.getDropTargetProtocols(); 357 } 358 359 /* Grab server, since we are working with the window that belongs to 360 another client. */ 361 XlibWrapper.XGrabServer(XToolkit.getDisplay()); 362 try { 363 while (dropTargetProtocols.hasNext()) { 364 XDropTargetProtocol dropTargetProtocol = 365 (XDropTargetProtocol)dropTargetProtocols.next(); 366 if (!isXEmbedServer || !dropTargetProtocol.isXEmbedSupported()) { 367 dropTargetProtocol.registerEmbedderDropSite(embedder); 368 } 369 } 370 } finally { 371 XlibWrapper.XUngrabServer(XToolkit.getDisplay()); 372 } 373 } 374 375 private void unregisterEmbedderDropSite(long embedder, 376 EmbeddedDropSiteEntry entry) { 377 assert XToolkit.isAWTLockHeldByCurrentThread(); 378 379 Iterator dropTargetProtocols = 380 XDragAndDropProtocols.getDropTargetProtocols(); 381 382 /* Grab server, since we are working with the window that belongs to 383 another client. */ 384 XlibWrapper.XGrabServer(XToolkit.getDisplay()); 385 try { 386 while (dropTargetProtocols.hasNext()) { 387 XDropTargetProtocol dropTargetProtocol = 388 (XDropTargetProtocol)dropTargetProtocols.next(); 389 dropTargetProtocol.unregisterEmbedderDropSite(embedder); 390 } 391 392 long event_mask = entry.getEventMask(); 393 394 /* Restore the original event mask for the embedder. */ 395 if ((event_mask & XConstants.PropertyChangeMask) == 0) { 396 XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 397 XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder, 398 event_mask); 399 XErrorHandlerUtil.RESTORE_XERROR_HANDLER(); 400 401 if ((XErrorHandlerUtil.saved_error != null) && 402 (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) { 403 throw new XException("XSelectInput failed"); 404 } 405 } 406 } finally { 407 XlibWrapper.XUngrabServer(XToolkit.getDisplay()); 408 } 409 } 410 411 private void registerEmbeddedDropSite(long toplevel, long window) { 412 XBaseWindow xBaseWindow = XToolkit.windowToXWindow(window); 413 boolean isXEmbedClient = 414 (xBaseWindow instanceof XEmbeddedFramePeer) && 415 ((XEmbeddedFramePeer)xBaseWindow).isXEmbedActive(); 416 417 XEmbedCanvasPeer peer = null; 418 { 419 XBaseWindow xbaseWindow = XToolkit.windowToXWindow(toplevel); 420 if (xbaseWindow != null) { 421 if (xbaseWindow instanceof XEmbedCanvasPeer) { 422 peer = (XEmbedCanvasPeer)xbaseWindow; 423 } else { 424 throw new UnsupportedOperationException(); 425 } 426 } 427 } 428 429 Long lToplevel = Long.valueOf(toplevel); 430 EmbeddedDropSiteEntry entry = null; 431 synchronized (this) { 432 entry = embeddedDropSiteRegistry.get(lToplevel); 433 if (entry == null) { 434 if (peer != null) { 435 // Toplevel is an XEmbed server within this VM. 436 // Register an XEmbed drop site. 437 peer.setXEmbedDropTarget(); 438 // Create a dummy entry to register the embedded site. 439 entry = new EmbeddedDropSiteEntry(0, 0, 440 Collections.<XDropTargetProtocol>emptyList()); 441 } else { 442 // Foreign toplevel. 443 // Select for PropertyNotify events on the toplevel, so that 444 // we can track changes of the properties relevant to DnD 445 // protocols. 446 entry = registerEmbedderDropSite(toplevel); 447 // Register the toplevel with all DnD protocols that are not 448 // supported by XEmbed - actually setup a proxy, so that 449 // all DnD notifications sent to the toplevel are first 450 // routed to us. 451 registerProtocols(toplevel, NON_XEMBED_PROTOCOLS, 452 entry.getSupportedProtocols()); 453 } 454 embeddedDropSiteRegistry.put(lToplevel, entry); 455 } 456 } 457 458 assert entry != null; 459 460 synchronized (entry) { 461 // For a foreign toplevel. 462 if (peer == null) { 463 if (!isXEmbedClient) { 464 // Since this is not an XEmbed client we can no longer rely 465 // on XEmbed to route DnD notifications even for DnD 466 // protocols that are supported by XEmbed. 467 // We rollback to the XEmbed-unfriendly solution - setup 468 // a proxy, so that all DnD notifications sent to the 469 // toplevel are first routed to us. 470 registerProtocols(toplevel, XEMBED_PROTOCOLS, 471 entry.getSupportedProtocols()); 472 } else { 473 Iterator dropTargetProtocols = 474 XDragAndDropProtocols.getDropTargetProtocols(); 475 476 // Register the embedded window as a plain drop site with 477 // all DnD protocols that are supported by XEmbed. 478 while (dropTargetProtocols.hasNext()) { 479 XDropTargetProtocol dropTargetProtocol = 480 (XDropTargetProtocol)dropTargetProtocols.next(); 481 if (dropTargetProtocol.isXEmbedSupported()) { 482 dropTargetProtocol.registerEmbedderDropSite(window); 483 } 484 } 485 } 486 } 487 488 entry.addSite(window, isXEmbedClient); 489 } 490 } 491 492 private void unregisterEmbeddedDropSite(long toplevel, long window) { 493 Long lToplevel = Long.valueOf(toplevel); 494 EmbeddedDropSiteEntry entry = null; 495 synchronized (this) { 496 entry = embeddedDropSiteRegistry.get(lToplevel); 497 if (entry == null) { 498 return; 499 } 500 entry.removeSite(window); 501 if (!entry.hasSites()) { 502 embeddedDropSiteRegistry.remove(lToplevel); 503 504 XBaseWindow xbaseWindow = XToolkit.windowToXWindow(toplevel); 505 if (xbaseWindow != null) { 506 if (xbaseWindow instanceof XEmbedCanvasPeer) { 507 XEmbedCanvasPeer peer = (XEmbedCanvasPeer)xbaseWindow; 508 // Unregister an XEmbed drop site. 509 peer.removeXEmbedDropTarget(); 510 } else { 511 throw new UnsupportedOperationException(); 512 } 513 } else { 514 unregisterEmbedderDropSite(toplevel, entry); 515 } 516 } 517 } 518 } 519 520 /* 521 * Returns a drop site that is embedded in the specified embedder window and 522 * contains the point with the specified root coordinates. 523 */ 524 public long getEmbeddedDropSite(long embedder, int x, int y) { 525 Long lToplevel = Long.valueOf(embedder); 526 EmbeddedDropSiteEntry entry = embeddedDropSiteRegistry.get(lToplevel); 527 if (entry == null) { 528 return 0; 529 } 530 return entry.getSite(x, y); 531 } 532 533 /* 534 * Note: this method should be called under AWT lock. 535 */ 536 public void registerDropSite(long window) { 537 assert XToolkit.isAWTLockHeldByCurrentThread(); 538 539 if (window == 0) { 540 throw new IllegalArgumentException(); 541 } 542 543 XDropTargetEventProcessor.activate(); 544 545 long toplevel = getToplevelWindow(window); 546 547 /* 548 * No window with WM_STATE property is found. 549 * Since the window can be a plugin window reparented to the browser 550 * toplevel, we cannot determine which window will eventually have 551 * WM_STATE property set. So we schedule a timer callback that will 552 * periodically attempt to find an ancestor with WM_STATE and 553 * register the drop site appropriately. 554 */ 555 if (toplevel == 0) { 556 addDelayedRegistrationEntry(window); 557 return; 558 } 559 560 if (toplevel == window) { 561 Iterator dropTargetProtocols = 562 XDragAndDropProtocols.getDropTargetProtocols(); 563 564 while (dropTargetProtocols.hasNext()) { 565 XDropTargetProtocol dropTargetProtocol = 566 (XDropTargetProtocol)dropTargetProtocols.next(); 567 dropTargetProtocol.registerDropTarget(toplevel); 568 } 569 } else { 570 registerEmbeddedDropSite(toplevel, window); 571 } 572 } 573 574 /* 575 * Note: this method should be called under AWT lock. 576 */ 577 public void unregisterDropSite(long window) { 578 assert XToolkit.isAWTLockHeldByCurrentThread(); 579 580 if (window == 0) { 581 throw new IllegalArgumentException(); 582 } 583 584 long toplevel = getToplevelWindow(window); 585 586 if (toplevel == window) { 587 Iterator dropProtocols = 588 XDragAndDropProtocols.getDropTargetProtocols(); 589 590 removeDelayedRegistrationEntry(window); 591 592 while (dropProtocols.hasNext()) { 593 XDropTargetProtocol dropProtocol = (XDropTargetProtocol)dropProtocols.next(); 594 dropProtocol.unregisterDropTarget(window); 595 } 596 } else { 597 unregisterEmbeddedDropSite(toplevel, window); 598 } 599 } 600 601 public void registerXEmbedClient(long canvasWindow, long clientWindow) { 602 // If the client has an associated XDnD drop site, add a drop target 603 // to the XEmbedCanvasPeer's target to route drag notifications to the 604 // client. 605 606 XDragSourceProtocol xdndDragProtocol = 607 XDragAndDropProtocols.getDragSourceProtocol(XDragAndDropProtocols.XDnD); 608 XDragSourceProtocol.TargetWindowInfo info = 609 xdndDragProtocol.getTargetWindowInfo(clientWindow); 610 if (info != null && 611 info.getProtocolVersion() >= XDnDConstants.XDND_MIN_PROTOCOL_VERSION) { 612 613 if (logger.isLoggable(PlatformLogger.Level.FINE)) { 614 logger.fine(" XEmbed drop site will be registered for " + Long.toHexString(clientWindow)); 615 } 616 registerEmbeddedDropSite(canvasWindow, clientWindow); 617 618 Iterator dropTargetProtocols = 619 XDragAndDropProtocols.getDropTargetProtocols(); 620 621 while (dropTargetProtocols.hasNext()) { 622 XDropTargetProtocol dropTargetProtocol = 623 (XDropTargetProtocol)dropTargetProtocols.next(); 624 dropTargetProtocol.registerEmbeddedDropSite(clientWindow); 625 } 626 627 if (logger.isLoggable(PlatformLogger.Level.FINE)) { 628 logger.fine(" XEmbed drop site has been registered for " + Long.toHexString(clientWindow)); 629 } 630 } 631 } 632 633 public void unregisterXEmbedClient(long canvasWindow, long clientWindow) { 634 if (logger.isLoggable(PlatformLogger.Level.FINE)) { 635 logger.fine(" XEmbed drop site will be unregistered for " + Long.toHexString(clientWindow)); 636 } 637 Iterator dropTargetProtocols = 638 XDragAndDropProtocols.getDropTargetProtocols(); 639 640 while (dropTargetProtocols.hasNext()) { 641 XDropTargetProtocol dropTargetProtocol = 642 (XDropTargetProtocol)dropTargetProtocols.next(); 643 dropTargetProtocol.unregisterEmbeddedDropSite(clientWindow); 644 } 645 646 unregisterEmbeddedDropSite(canvasWindow, clientWindow); 647 648 if (logger.isLoggable(PlatformLogger.Level.FINE)) { 649 logger.fine(" XEmbed drop site has beed unregistered for " + Long.toHexString(clientWindow)); 650 } 651 } 652 653 /**************** Delayed drop site registration *******************************/ 654 655 private void addDelayedRegistrationEntry(final long window) { 656 Long lWindow = Long.valueOf(window); 657 Runnable runnable = new Runnable() { 658 public void run() { 659 removeDelayedRegistrationEntry(window); 660 registerDropSite(window); 661 } 662 }; 663 664 XToolkit.awtLock(); 665 try { 666 removeDelayedRegistrationEntry(window); 667 delayedRegistrationMap.put(lWindow, runnable); 668 XToolkit.schedule(runnable, DELAYED_REGISTRATION_PERIOD); 669 } finally { 670 XToolkit.awtUnlock(); 671 } 672 } 673 674 private void removeDelayedRegistrationEntry(long window) { 675 Long lWindow = Long.valueOf(window); 676 677 XToolkit.awtLock(); 678 try { 679 Runnable runnable = delayedRegistrationMap.remove(lWindow); 680 if (runnable != null) { 681 XToolkit.remove(runnable); 682 } 683 } finally { 684 XToolkit.awtUnlock(); 685 } 686 } 687 /*******************************************************************************/ 688 }