package cz.matejsimek.scup;
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.MouseInfo;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.List;
/**
* Clipboard listener which decide what to do with clipboard content
*
* @author Matej Simek | www.matejsimek.cz
*/
public class ClipboardChangeListener extends Thread {
/**
* Data source
*/
private Clipboard clipboard;
/**
* Dimension of virtual desktop needed to decide from what source image is
*/
private Dimension virtualSize;
/**
* Indicates multiple display setup
*/
private boolean multipleDisplays = false;
@Override
public void run() {
Scup.setClipboard("");
System.out.println("Starting clipboard listener...");
BufferedImage oldImage = null;
List<File> oldFiles = null;
while (true) {
try {
// Text in clipboard idicates free way to clear old references
if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) {
if (oldImage != null) {
oldImage.flush();
}
oldImage = null;
oldFiles = null;
} // Compare old image with new one from clipboard if its available
else if (clipboard.isDataFlavorAvailable(DataFlavor.imageFlavor)) {
BufferedImage newImage = (BufferedImage) clipboard.getData(DataFlavor.imageFlavor);
clipboard.setContents(new StringSelection(""), null);
if (!newImage.equals(oldImage)) {
System.out.println("New image detected in clipboard");
if (oldImage != null) {
oldImage.flush();
}
oldImage = newImage;
processImageContent(newImage);
} else {
newImage.flush();
newImage = null;
}
} // Compare old file list with new one from clipboard if its available
else if (clipboard.isDataFlavorAvailable(DataFlavor.javaFileListFlavor)) {
List<File> newFiles = (List<File>) clipboard.getData(DataFlavor.javaFileListFlavor);
if (!newFiles.equals(oldFiles)) {
System.out.println("New files detected in clipboard");
oldFiles = newFiles;
processFileContent(newFiles);
} else {
newFiles = null;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
synchronized (this) {
try {
this.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
/**
* Detect dimensions of virtual space and save them to
* <code>Dimension virtualSize</code> and
* <code>Point virtualOrigin</code>
*/
void detectVirtualDimensions() {
GraphicsEnvironment ge;
ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
Rectangle vBounds = new Rectangle();
GraphicsDevice[] gdArray = ge.getScreenDevices();
for (int i = 0; i < gdArray.length; i++) {
GraphicsDevice gd = gdArray[i];
GraphicsConfiguration[] gcArray = gd.getConfigurations();
for (int j = 0; j < gcArray.length; j++) {
vBounds = vBounds.union(gcArray[j].getBounds());
}
}
multipleDisplays = gdArray.length > 1 ? true : false;
virtualSize = vBounds.getSize();
}
/**
*
* @param clipboard Data source
* @param monitorAll Capture images from all sources, not only printscreen
*/
public ClipboardChangeListener(Clipboard clipboard) {
this.clipboard = clipboard;
}
/**
* Basic image content handling - determinates image source and
*
* @param image
*/
public void processImageContent(BufferedImage image) {
GraphicsDevice currentDevice = MouseInfo.getPointerInfo().getDevice();
detectVirtualDimensions();
// Decide from what source is image in clipboard based on its dimensions
if (image.getWidth() < virtualSize.width || image.getHeight() < virtualSize.height) {
// Custom source
if (Scup.MONITOR_ALL) {
Scup.processImage(image, false, currentDevice);
} else {
System.out.println("Skipping image, Monitor all is disabled.");
}
image.flush();
image = null;
} else {
if (multipleDisplays) {
try {
image.flush();
image = null;
// Full print screen in clipboard, make screen again but only for active device
Robot robot = new Robot();
BufferedImage newImage = robot.createScreenCapture(currentDevice.getDefaultConfiguration().getBounds());
Scup.processImage(newImage, true, currentDevice);
newImage.flush();
newImage = null;
} catch (AWTException ex) {
ex.printStackTrace();
}
} else {
Scup.processImage(image, true, currentDevice);
image.flush();
image = null;
}
}
System.gc();
}
/**
* Basic file content handling (only calls Scup.processFiles when
* Scup.MONITOR_ALL is true)
*
* @param files
*/
public void processFileContent(List<File> files) {
if (Scup.MONITOR_ALL) {
Scup.processFiles(files);
} else {
System.out.println("Skippign files, Monitor all is disabled.");
}
}
}