51 import sun.awt.SunToolkit; 52 53 54 /** 55 * Serves as a common, helper superclass for the Win32 and X11 system 56 * Clipboards. 57 * 58 * @author Danila Sinopalnikov 59 * @author Alexander Gerasimov 60 * 61 * @since 1.3 62 */ 63 public abstract class SunClipboard extends Clipboard 64 implements PropertyChangeListener { 65 66 private AppContext contentsContext = null; 67 68 private final Object CLIPBOARD_FLAVOR_LISTENER_KEY; 69 70 /** 71 * A number of <code>FlavorListener</code>s currently registered 72 * on this clipboard across all <code>AppContext</code>s. 73 */ 74 private volatile int numberOfFlavorListeners = 0; 75 76 /** 77 * A set of {@code DataFlavor}s that is available on this clipboard. It is 78 * used for tracking changes of {@code DataFlavor}s available on this 79 * clipboard. Can be {@code null}. 80 */ 81 private volatile long[] currentFormats; 82 83 public SunClipboard(String name) { 84 super(name); 85 CLIPBOARD_FLAVOR_LISTENER_KEY = new StringBuffer(name + "_CLIPBOARD_FLAVOR_LISTENER_KEY"); 86 } 87 88 public synchronized void setContents(Transferable contents, 89 ClipboardOwner owner) { 90 // 4378007 : Toolkit.getSystemClipboard().setContents(null, null) 91 // should throw NPE 92 if (contents == null) { 245 public void openClipboard(SunClipboard newOwner) {} 246 public void closeClipboard() {} 247 248 public abstract long getID(); 249 250 public void propertyChange(PropertyChangeEvent evt) { 251 if (AppContext.DISPOSED_PROPERTY_NAME.equals(evt.getPropertyName()) && 252 Boolean.TRUE.equals(evt.getNewValue())) { 253 final AppContext disposedContext = (AppContext)evt.getSource(); 254 lostOwnershipLater(disposedContext); 255 } 256 } 257 258 protected void lostOwnershipImpl() { 259 lostOwnershipLater(null); 260 } 261 262 /** 263 * Clears the clipboard state (contents, owner and contents context) and 264 * notifies the current owner that ownership is lost. Does nothing if the 265 * argument is not <code>null</code> and is not equal to the current 266 * contents context. 267 * 268 * @param disposedContext the AppContext that is disposed or 269 * <code>null</code> if the ownership is lost because another 270 * application acquired ownership. 271 */ 272 protected void lostOwnershipLater(final AppContext disposedContext) { 273 final AppContext context = this.contentsContext; 274 if (context == null) { 275 return; 276 } 277 278 SunToolkit.postEvent(context, new PeerEvent(this, () -> lostOwnershipNow(disposedContext), 279 PeerEvent.PRIORITY_EVENT)); 280 } 281 282 protected void lostOwnershipNow(final AppContext disposedContext) { 283 final SunClipboard sunClipboard = SunClipboard.this; 284 ClipboardOwner owner = null; 285 Transferable contents = null; 286 287 synchronized (sunClipboard) { 288 final AppContext context = sunClipboard.contentsContext; 289 388 @SuppressWarnings("unchecked") 389 private Set<FlavorListener> getFlavorListeners(AppContext appContext) { 390 return (Set<FlavorListener>)appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY); 391 } 392 393 public synchronized FlavorListener[] getFlavorListeners() { 394 Set<FlavorListener> flavorListeners = getFlavorListeners(AppContext.getAppContext()); 395 return flavorListeners == null ? new FlavorListener[0] 396 : flavorListeners.toArray(new FlavorListener[flavorListeners.size()]); 397 } 398 399 public boolean areFlavorListenersRegistered() { 400 return (numberOfFlavorListeners > 0); 401 } 402 403 protected abstract void registerClipboardViewerChecked(); 404 405 protected abstract void unregisterClipboardViewerChecked(); 406 407 /** 408 * Checks change of the <code>DataFlavor</code>s and, if necessary, 409 * posts notifications on <code>FlavorEvent</code>s to the 410 * AppContexts' EDTs. 411 * The parameter <code>formats</code> is null iff we have just 412 * failed to get formats available on the clipboard. 413 * 414 * @param formats data formats that have just been retrieved from 415 * this clipboard 416 */ 417 protected final void checkChange(final long[] formats) { 418 if (Arrays.equals(formats, currentFormats)) { 419 // we've been able to successfully get available on the clipboard 420 // DataFlavors this and previous time and they are coincident; 421 // don't notify 422 return; 423 } 424 currentFormats = formats; 425 426 for (final AppContext appContext : AppContext.getAppContexts()) { 427 if (appContext == null || appContext.isDisposed()) { 428 continue; 429 } 430 Set<FlavorListener> flavorListeners = getFlavorListeners(appContext); 431 if (flavorListeners != null) { | 51 import sun.awt.SunToolkit; 52 53 54 /** 55 * Serves as a common, helper superclass for the Win32 and X11 system 56 * Clipboards. 57 * 58 * @author Danila Sinopalnikov 59 * @author Alexander Gerasimov 60 * 61 * @since 1.3 62 */ 63 public abstract class SunClipboard extends Clipboard 64 implements PropertyChangeListener { 65 66 private AppContext contentsContext = null; 67 68 private final Object CLIPBOARD_FLAVOR_LISTENER_KEY; 69 70 /** 71 * A number of {@code FlavorListener}s currently registered 72 * on this clipboard across all {@code AppContext}s. 73 */ 74 private volatile int numberOfFlavorListeners = 0; 75 76 /** 77 * A set of {@code DataFlavor}s that is available on this clipboard. It is 78 * used for tracking changes of {@code DataFlavor}s available on this 79 * clipboard. Can be {@code null}. 80 */ 81 private volatile long[] currentFormats; 82 83 public SunClipboard(String name) { 84 super(name); 85 CLIPBOARD_FLAVOR_LISTENER_KEY = new StringBuffer(name + "_CLIPBOARD_FLAVOR_LISTENER_KEY"); 86 } 87 88 public synchronized void setContents(Transferable contents, 89 ClipboardOwner owner) { 90 // 4378007 : Toolkit.getSystemClipboard().setContents(null, null) 91 // should throw NPE 92 if (contents == null) { 245 public void openClipboard(SunClipboard newOwner) {} 246 public void closeClipboard() {} 247 248 public abstract long getID(); 249 250 public void propertyChange(PropertyChangeEvent evt) { 251 if (AppContext.DISPOSED_PROPERTY_NAME.equals(evt.getPropertyName()) && 252 Boolean.TRUE.equals(evt.getNewValue())) { 253 final AppContext disposedContext = (AppContext)evt.getSource(); 254 lostOwnershipLater(disposedContext); 255 } 256 } 257 258 protected void lostOwnershipImpl() { 259 lostOwnershipLater(null); 260 } 261 262 /** 263 * Clears the clipboard state (contents, owner and contents context) and 264 * notifies the current owner that ownership is lost. Does nothing if the 265 * argument is not {@code null} and is not equal to the current 266 * contents context. 267 * 268 * @param disposedContext the AppContext that is disposed or 269 * {@code null} if the ownership is lost because another 270 * application acquired ownership. 271 */ 272 protected void lostOwnershipLater(final AppContext disposedContext) { 273 final AppContext context = this.contentsContext; 274 if (context == null) { 275 return; 276 } 277 278 SunToolkit.postEvent(context, new PeerEvent(this, () -> lostOwnershipNow(disposedContext), 279 PeerEvent.PRIORITY_EVENT)); 280 } 281 282 protected void lostOwnershipNow(final AppContext disposedContext) { 283 final SunClipboard sunClipboard = SunClipboard.this; 284 ClipboardOwner owner = null; 285 Transferable contents = null; 286 287 synchronized (sunClipboard) { 288 final AppContext context = sunClipboard.contentsContext; 289 388 @SuppressWarnings("unchecked") 389 private Set<FlavorListener> getFlavorListeners(AppContext appContext) { 390 return (Set<FlavorListener>)appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY); 391 } 392 393 public synchronized FlavorListener[] getFlavorListeners() { 394 Set<FlavorListener> flavorListeners = getFlavorListeners(AppContext.getAppContext()); 395 return flavorListeners == null ? new FlavorListener[0] 396 : flavorListeners.toArray(new FlavorListener[flavorListeners.size()]); 397 } 398 399 public boolean areFlavorListenersRegistered() { 400 return (numberOfFlavorListeners > 0); 401 } 402 403 protected abstract void registerClipboardViewerChecked(); 404 405 protected abstract void unregisterClipboardViewerChecked(); 406 407 /** 408 * Checks change of the {@code DataFlavor}s and, if necessary, 409 * posts notifications on {@code FlavorEvent}s to the 410 * AppContexts' EDTs. 411 * The parameter {@code formats} is null iff we have just 412 * failed to get formats available on the clipboard. 413 * 414 * @param formats data formats that have just been retrieved from 415 * this clipboard 416 */ 417 protected final void checkChange(final long[] formats) { 418 if (Arrays.equals(formats, currentFormats)) { 419 // we've been able to successfully get available on the clipboard 420 // DataFlavors this and previous time and they are coincident; 421 // don't notify 422 return; 423 } 424 currentFormats = formats; 425 426 for (final AppContext appContext : AppContext.getAppContexts()) { 427 if (appContext == null || appContext.isDisposed()) { 428 continue; 429 } 430 Set<FlavorListener> flavorListeners = getFlavorListeners(appContext); 431 if (flavorListeners != null) { |