From 6a383c102b282e1107338bef6178e0ce538afa78 Mon Sep 17 00:00:00 2001 From: sgoudham Date: Thu, 22 Jul 2021 03:01:26 +0100 Subject: [PATCH] Add listeners for different operating systems with different implementations --- .../goudham/listener/ClipboardListener.java | 5 ++ .../listener/MacClipboardListener.java | 59 ++++++++++++++++ .../WindowsOrUnixClipboardListener.java | 67 +++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 src/main/java/me/goudham/listener/ClipboardListener.java create mode 100644 src/main/java/me/goudham/listener/MacClipboardListener.java create mode 100644 src/main/java/me/goudham/listener/WindowsOrUnixClipboardListener.java diff --git a/src/main/java/me/goudham/listener/ClipboardListener.java b/src/main/java/me/goudham/listener/ClipboardListener.java new file mode 100644 index 0000000..16bc434 --- /dev/null +++ b/src/main/java/me/goudham/listener/ClipboardListener.java @@ -0,0 +1,5 @@ +package me.goudham.listener; + +public interface ClipboardListener { + void execute(); +} diff --git a/src/main/java/me/goudham/listener/MacClipboardListener.java b/src/main/java/me/goudham/listener/MacClipboardListener.java new file mode 100644 index 0000000..caf83df --- /dev/null +++ b/src/main/java/me/goudham/listener/MacClipboardListener.java @@ -0,0 +1,59 @@ +package me.goudham.listener; + +import java.awt.Dimension; +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import me.goudham.model.MyClipboardContent; +import me.goudham.util.ClipboardUtils; +import org.jetbrains.annotations.NotNull; + +import static me.goudham.model.Contents.IMAGE; +import static me.goudham.model.Contents.STRING; + +public class MacClipboardListener implements ClipboardListener { + private final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + private final @NotNull ClipboardEvent clipboardEvent; + + public MacClipboardListener(@NotNull ClipboardEvent clipboardEvent) { + this.clipboardEvent = clipboardEvent; + } + + @Override + public void execute() { + Transferable oldClipboardContents = clipboard.getContents(null); + final MyClipboardContent[] myOldClipboardContentsArray = new MyClipboardContent[]{ ClipboardUtils.getClipboardContents(oldClipboardContents, clipboard) }; + + ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + executor.scheduleAtFixedRate(() -> { + Transferable newClipboardContents = clipboard.getContents(null); + MyClipboardContent myNewClipboardContents = new MyClipboardContent<>(""); + + try { + if (STRING.isAvailable(clipboard)) { + myNewClipboardContents.setContent(newClipboardContents.getTransferData(STRING.getDataFlavor())); + if (!myNewClipboardContents.getContent().equals(myOldClipboardContentsArray[0].getContent())) { + clipboardEvent.onCopyString((String) myNewClipboardContents.getContent()); + myOldClipboardContentsArray[0].setContent(myNewClipboardContents.getContent()); + } + } else if (IMAGE.isAvailable(clipboard)) { + BufferedImage bufferedImage = ClipboardUtils.convertToBufferedImage((Image) newClipboardContents.getTransferData(IMAGE.getDataFlavor())); + myNewClipboardContents.setContent(new Dimension(bufferedImage.getWidth(), bufferedImage.getHeight())); + if (!myNewClipboardContents.getContent().equals(myOldClipboardContentsArray[0].getContent())) { + clipboardEvent.onCopyImage(bufferedImage); + myOldClipboardContentsArray[0].setContent(myNewClipboardContents.getContent()); + } + } + } catch (UnsupportedFlavorException | IOException exp) { + exp.printStackTrace(); + } + }, 0, 350, TimeUnit.MILLISECONDS); + } +} diff --git a/src/main/java/me/goudham/listener/WindowsOrUnixClipboardListener.java b/src/main/java/me/goudham/listener/WindowsOrUnixClipboardListener.java new file mode 100644 index 0000000..8573971 --- /dev/null +++ b/src/main/java/me/goudham/listener/WindowsOrUnixClipboardListener.java @@ -0,0 +1,67 @@ +package me.goudham.listener; + +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.image.BufferedImage; +import java.io.IOException; +import me.goudham.util.ClipboardUtils; +import org.jetbrains.annotations.NotNull; + +public class WindowsOrUnixClipboardListener extends Thread implements ClipboardListener, ClipboardOwner { + private final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + private final @NotNull ClipboardEvent clipboardEvent; + + public WindowsOrUnixClipboardListener(@NotNull ClipboardEvent clipboardEvent) { + this.clipboardEvent = clipboardEvent; + } + + @Override + public void lostOwnership(Clipboard oldClipboard, Transferable oldClipboardContents) { + try { + sleep(200); + } catch (InterruptedException ignored) { + } + + Transferable newClipboardContents = oldClipboard.getContents(currentThread()); + processContents(oldClipboard, newClipboardContents); + regainOwnership(oldClipboard, newClipboardContents); + } + + public void processContents(Clipboard oldClipboard, Transferable newClipboardContents) { + try { + if (oldClipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) { + String stringContent = (String) newClipboardContents.getTransferData(DataFlavor.stringFlavor); + clipboardEvent.onCopyString(stringContent); + } else if (oldClipboard.isDataFlavorAvailable(DataFlavor.imageFlavor)) { + BufferedImage imageContent = ClipboardUtils.convertToBufferedImage((Image) newClipboardContents.getTransferData(DataFlavor.imageFlavor)); + clipboardEvent.onCopyImage(imageContent); + } + } catch (UnsupportedFlavorException | IOException ignored) { + } + } + + public void regainOwnership(Clipboard clipboard, Transferable newClipboardContents) { + try { + clipboard.setContents(newClipboardContents, this); + } catch (IllegalStateException ise) { + try { + sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + regainOwnership(clipboard, newClipboardContents); + } + } + + @Override + public void execute() { + Transferable currentClipboardContents = clipboard.getContents(null); + processContents(clipboard, currentClipboardContents); + regainOwnership(clipboard, currentClipboardContents); + } +} \ No newline at end of file