Skip to content

Commit 6197d4a

Browse files
committed
Add getContentsAsync methods to Clipboard
Obtaining data from the clipboard is fundamentally an asynchronous operation, the event loop, at least at the OS level, needs to run for the data to become available. This PR proposes new API that provides asynchronous equivalents of getContents methods called getContentsAsync that return CompleteableFutures. This new API will allow SWT API consumers to interact better with the clipboard when the OS (window system) API is actually implemented in an asynchronous manner. GTK3 and cocoa provides API that spins the event loop as needed so that a synchronous looking API can be provided to the user of the API. For example, in SWT we use gtk_clipboard_wait_for_contents which spins the loop in the GTK library itself [here](https://gitlab.gnome.org/GNOME/gtk/-/blob/716458e86a222f43e64f7a4feda37749f3469ee4/gtk/gtkclipboard.c#L1436) GTK4 does not provide such an API and leaves it to the user of the API to spin the event loop. Win32 is somewhat of a hybrid. The API appears synchronous, but SWT needs to spin in a couple of places, such as [getData](https://github.com/eclipse-platform/eclipse.platform.swt/blob/63e8925dc77db3b93ef521dc6cf2bd6ded7bab64/bundles/org.eclipse.swt/Eclipse%20SWT%20Drag%20and%20Drop/win32/org/eclipse/swt/dnd/Transfer.java#L46) Part of #2598 and #2126
1 parent 7831aa5 commit 6197d4a

File tree

5 files changed

+347
-54
lines changed

5 files changed

+347
-54
lines changed

bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/cocoa/org/eclipse/swt/dnd/Clipboard.java

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*******************************************************************************/
1414
package org.eclipse.swt.dnd;
1515

16+
import java.util.concurrent.*;
1617

1718
import org.eclipse.swt.*;
1819
import org.eclipse.swt.internal.cocoa.*;
@@ -308,6 +309,90 @@ public Object getContents(Transfer transfer, int clipboards) {
308309
return null;
309310
}
310311

312+
/**
313+
* Retrieve the data of the specified type currently available on the system
314+
* clipboard. Refer to the specific subclass of <code>Transfer</code> to
315+
* determine the type of object returned.
316+
*
317+
* <p>This method is asynchronous and may require the SWT event loop to
318+
* iterate before the future will complete.</p>
319+
*
320+
* <p>The following snippet shows text being retrieved from the clipboard:</p>
321+
*
322+
* <pre><code>
323+
* Clipboard clipboard = new Clipboard(display);
324+
* TextTransfer textTransfer = TextTransfer.getInstance();
325+
* CompletableFuture&lt;Object&gt; future = clipboard.getContentsAsync(textTransfer);
326+
* future.thenAccept(textData -&gt; System.out.println("Text is "+textData));
327+
* clipboard.dispose();
328+
* </code></pre>
329+
*
330+
* @param transfer the transfer agent for the type of data being requested
331+
* @return the future whose value will resolve to the data obtained from the
332+
* clipboard or will resolve to null if no data of this type is available
333+
*
334+
* @exception SWTException <ul>
335+
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
336+
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
337+
* </ul>
338+
* @exception IllegalArgumentException <ul>
339+
* <li>ERROR_NULL_ARGUMENT - if transfer is null</li>
340+
* </ul>
341+
*
342+
* @see Transfer
343+
* @since 3.132
344+
*/
345+
public CompletableFuture<Object> getContentsAsync(Transfer transfer) {
346+
return getContentsAsync(transfer, DND.CLIPBOARD);
347+
}
348+
349+
/**
350+
* Retrieve the data of the specified type currently available on the specified
351+
* clipboard. Refer to the specific subclass of <code>Transfer</code> to
352+
* determine the type of object returned.
353+
*
354+
* <p>This method is asynchronous and may require the SWT event loop to
355+
* iterate before the future will complete.</p>
356+
*
357+
* <p>The following snippet shows text being retrieved from the clipboard:</p>
358+
*
359+
* <pre><code>
360+
* Clipboard clipboard = new Clipboard(display);
361+
* TextTransfer textTransfer = TextTransfer.getInstance();
362+
* CompletableFuture&lt;Object&gt; future = clipboard.getContentsAsync(textTransfer, DND.CLIPBOARD);
363+
* future.thenAccept(textData -&gt; System.out.println("Text is "+textData));
364+
* clipboard.dispose();
365+
* </code></pre>
366+
*
367+
* <p>The clipboards value is either one of the clipboard constants defined in
368+
* class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together
369+
* (that is, using the <code>int</code> "|" operator) two or more
370+
* of those <code>DND</code> clipboard constants.</p>
371+
*
372+
* @param transfer the transfer agent for the type of data being requested
373+
* @param clipboards on which to look for data
374+
*
375+
* @return the future whose value will resolve to the data obtained from the
376+
* clipboard or will resolve to null if no data of this type is available
377+
*
378+
* @exception SWTException <ul>
379+
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
380+
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
381+
* </ul>
382+
* @exception IllegalArgumentException <ul>
383+
* <li>ERROR_NULL_ARGUMENT - if transfer is null</li>
384+
* </ul>
385+
*
386+
* @see Transfer
387+
* @see DND#CLIPBOARD
388+
* @see DND#SELECTION_CLIPBOARD
389+
*
390+
* @since 3.132
391+
*/
392+
public CompletableFuture<Object> getContentsAsync(Transfer transfer, int clipboards) {
393+
return CompletableFuture.completedFuture(getContents(transfer, clipboards));
394+
}
395+
311396
/**
312397
* Returns <code>true</code> if the clipboard has been disposed,
313398
* and <code>false</code> otherwise.

bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/gtk/org/eclipse/swt/dnd/Clipboard.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
package org.eclipse.swt.dnd;
1515

1616

17+
import java.util.concurrent.*;
18+
1719
import org.eclipse.swt.*;
1820
import org.eclipse.swt.graphics.*;
1921
import org.eclipse.swt.internal.*;
@@ -326,6 +328,90 @@ public Object getContents(Transfer transfer, int clipboards) {
326328
return result;
327329
}
328330

331+
/**
332+
* Retrieve the data of the specified type currently available on the system
333+
* clipboard. Refer to the specific subclass of <code>Transfer</code> to
334+
* determine the type of object returned.
335+
*
336+
* <p>This method is asynchronous and may require the SWT event loop to
337+
* iterate before the future will complete.</p>
338+
*
339+
* <p>The following snippet shows text being retrieved from the clipboard:</p>
340+
*
341+
* <pre><code>
342+
* Clipboard clipboard = new Clipboard(display);
343+
* TextTransfer textTransfer = TextTransfer.getInstance();
344+
* CompletableFuture&lt;Object&gt; future = clipboard.getContentsAsync(textTransfer);
345+
* future.thenAccept(textData -&gt; System.out.println("Text is "+textData));
346+
* clipboard.dispose();
347+
* </code></pre>
348+
*
349+
* @param transfer the transfer agent for the type of data being requested
350+
* @return the future whose value will resolve to the data obtained from the
351+
* clipboard or will resolve to null if no data of this type is available
352+
*
353+
* @exception SWTException <ul>
354+
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
355+
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
356+
* </ul>
357+
* @exception IllegalArgumentException <ul>
358+
* <li>ERROR_NULL_ARGUMENT - if transfer is null</li>
359+
* </ul>
360+
*
361+
* @see Transfer
362+
* @since 3.132
363+
*/
364+
public CompletableFuture<Object> getContentsAsync(Transfer transfer) {
365+
return getContentsAsync(transfer, DND.CLIPBOARD);
366+
}
367+
368+
/**
369+
* Retrieve the data of the specified type currently available on the specified
370+
* clipboard. Refer to the specific subclass of <code>Transfer</code> to
371+
* determine the type of object returned.
372+
*
373+
* <p>This method is asynchronous and may require the SWT event loop to
374+
* iterate before the future will complete.</p>
375+
*
376+
* <p>The following snippet shows text being retrieved from the clipboard:</p>
377+
*
378+
* <pre><code>
379+
* Clipboard clipboard = new Clipboard(display);
380+
* TextTransfer textTransfer = TextTransfer.getInstance();
381+
* CompletableFuture&lt;Object&gt; future = clipboard.getContentsAsync(textTransfer, DND.CLIPBOARD);
382+
* future.thenAccept(textData -&gt; System.out.println("Text is "+textData));
383+
* clipboard.dispose();
384+
* </code></pre>
385+
*
386+
* <p>The clipboards value is either one of the clipboard constants defined in
387+
* class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together
388+
* (that is, using the <code>int</code> "|" operator) two or more
389+
* of those <code>DND</code> clipboard constants.</p>
390+
*
391+
* @param transfer the transfer agent for the type of data being requested
392+
* @param clipboards on which to look for data
393+
*
394+
* @return the future whose value will resolve to the data obtained from the
395+
* clipboard or will resolve to null if no data of this type is available
396+
*
397+
* @exception SWTException <ul>
398+
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
399+
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
400+
* </ul>
401+
* @exception IllegalArgumentException <ul>
402+
* <li>ERROR_NULL_ARGUMENT - if transfer is null</li>
403+
* </ul>
404+
*
405+
* @see Transfer
406+
* @see DND#CLIPBOARD
407+
* @see DND#SELECTION_CLIPBOARD
408+
*
409+
* @since 3.132
410+
*/
411+
public CompletableFuture<Object> getContentsAsync(Transfer transfer, int clipboards) {
412+
return CompletableFuture.completedFuture(getContents(transfer, clipboards));
413+
}
414+
329415
private Object getContents_gtk4(Transfer transfer, int clipboards) {
330416

331417
long contents = GTK4.gdk_clipboard_get_content(Clipboard.GTKCLIPBOARD);

bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/Clipboard.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
*******************************************************************************/
1515
package org.eclipse.swt.dnd;
1616

17+
import java.util.concurrent.*;
1718

1819
import org.eclipse.swt.*;
1920
import org.eclipse.swt.internal.*;
@@ -367,6 +368,91 @@ public Object getContents(Transfer transfer, int clipboards) {
367368
}
368369
return null; // No data available for this transfer
369370
}
371+
372+
/**
373+
* Retrieve the data of the specified type currently available on the system
374+
* clipboard. Refer to the specific subclass of <code>Transfer</code> to
375+
* determine the type of object returned.
376+
*
377+
* <p>This method is asynchronous and may require the SWT event loop to
378+
* iterate before the future will complete.</p>
379+
*
380+
* <p>The following snippet shows text being retrieved from the clipboard:</p>
381+
*
382+
* <pre><code>
383+
* Clipboard clipboard = new Clipboard(display);
384+
* TextTransfer textTransfer = TextTransfer.getInstance();
385+
* CompletableFuture&lt;Object&gt; future = clipboard.getContentsAsync(textTransfer);
386+
* future.thenAccept(textData -&gt; System.out.println("Text is "+textData));
387+
* clipboard.dispose();
388+
* </code></pre>
389+
*
390+
* @param transfer the transfer agent for the type of data being requested
391+
* @return the future whose value will resolve to the data obtained from the
392+
* clipboard or will resolve to null if no data of this type is available
393+
*
394+
* @exception SWTException <ul>
395+
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
396+
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
397+
* </ul>
398+
* @exception IllegalArgumentException <ul>
399+
* <li>ERROR_NULL_ARGUMENT - if transfer is null</li>
400+
* </ul>
401+
*
402+
* @see Transfer
403+
* @since 3.132
404+
*/
405+
public CompletableFuture<Object> getContentsAsync(Transfer transfer) {
406+
return getContentsAsync(transfer, DND.CLIPBOARD);
407+
}
408+
409+
/**
410+
* Retrieve the data of the specified type currently available on the specified
411+
* clipboard. Refer to the specific subclass of <code>Transfer</code> to
412+
* determine the type of object returned.
413+
*
414+
* <p>This method is asynchronous and may require the SWT event loop to
415+
* iterate before the future will complete.</p>
416+
*
417+
* <p>The following snippet shows text being retrieved from the clipboard:</p>
418+
*
419+
* <pre><code>
420+
* Clipboard clipboard = new Clipboard(display);
421+
* TextTransfer textTransfer = TextTransfer.getInstance();
422+
* CompletableFuture&lt;Object&gt; future = clipboard.getContentsAsync(textTransfer, DND.CLIPBOARD);
423+
* future.thenAccept(textData -&gt; System.out.println("Text is "+textData));
424+
* clipboard.dispose();
425+
* </code></pre>
426+
*
427+
* <p>The clipboards value is either one of the clipboard constants defined in
428+
* class <code>DND</code>, or must be built by <em>bitwise OR</em>'ing together
429+
* (that is, using the <code>int</code> "|" operator) two or more
430+
* of those <code>DND</code> clipboard constants.</p>
431+
*
432+
* @param transfer the transfer agent for the type of data being requested
433+
* @param clipboards on which to look for data
434+
*
435+
* @return the future whose value will resolve to the data obtained from the
436+
* clipboard or will resolve to null if no data of this type is available
437+
*
438+
* @exception SWTException <ul>
439+
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
440+
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
441+
* </ul>
442+
* @exception IllegalArgumentException <ul>
443+
* <li>ERROR_NULL_ARGUMENT - if transfer is null</li>
444+
* </ul>
445+
*
446+
* @see Transfer
447+
* @see DND#CLIPBOARD
448+
* @see DND#SELECTION_CLIPBOARD
449+
*
450+
* @since 3.132
451+
*/
452+
public CompletableFuture<Object> getContentsAsync(Transfer transfer, int clipboards) {
453+
return CompletableFuture.completedFuture(getContents(transfer, clipboards));
454+
}
455+
370456
/**
371457
* Returns <code>true</code> if the clipboard has been disposed,
372458
* and <code>false</code> otherwise.

0 commit comments

Comments
 (0)