I want to be notified if a string is copied to the system clipboard. When a new string is copied from the same source application, the FlavorListener won't get an event. To get informed when another string is copied, i read the string from the clipboard, convert it to a SrtingSelection, which is able to take the ownership, and put it back to the clipboard. Now I got informed twice, once the StringSelection lost ownership and once it takes it back. Is there a way to check for the ownership directly, instead of storing the string and check it equals the new one? Here is my code so far:
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.FlavorListener;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws Exception {
// The clipboard
final Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
// read clipboard and take ownership to get the FlavorListener notified
// when the content has changed but the owner has not
processClipboard(cb);
cb.addFlavorListener(new FlavorListener() {
@Override
public void flavorsChanged(FlavorEvent e) {
processClipboard(cb);
}
});
// keep thread for testing
Thread.sleep(100000L);
}
public static void processClipboard(Clipboard cb) {
// gets the content of clipboard
Transferable trans = cb.getContents(null);
if (trans.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
// cast to string
String s = (String) trans
.getTransferData(DataFlavor.stringFlavor);
System.out.println(s);
// only StringSelection can take ownership, i think
StringSelection ss = new StringSelection(s);
// set content, take ownership
cb.setContents(ss, ss);
} catch (UnsupportedFlavorException e2) {
e2.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}
}
}
}
I hope you understand my bad english :-(
The previous answer is close to be working.
The real cure is to instead just monitor the event of ownership change. By the monitor's occupying the clipboard as owner when monitoring the clipboard, so when any application changes the clipboard, the ownership would change, so this would reliably indicate the clipboard content change. However, this approach must have sufficient wait to work, (200 ms was found to be working) after an ownership change event before accessing the clipboard and re-occupying the clipboard.
This solution was provided and proved to be working by marc weber at http://www.coderanch.com/t/377833/java/java/listen-clipboard
I have verified for my purpose. If needed, I can post the solution here.
Yu
To avoid double notification remove the flavor listener before setting the new clipboard content and add the listener again after setting clipboard content.
public class NewClass implements FlavorListener, ClipboardOwner{
private Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
public NewClass() {
System.out.println("NewClass constructor");
clip.setContents(clip.getContents(null), this);
clip.addFlavorListener(this);
try {
Thread.sleep(100000L);
}
catch (InterruptedException e) {
}
}
@Override
public void flavorsChanged(FlavorEvent e) {
System.out.println("ClipBoard Changed!!!");
clip.removeFlavorListener(this);
clip.setContents(clip.getContents(null), this);
clip.addFlavorListener(this);
}
@Override
public void lostOwnership(Clipboard arg0, Transferable arg1) {
System.out.println("ownership losted");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With