Question

I want to find a way to do kind of a custom "paste from clipboard" action. Let's assume the content of clipboard is text for simplicity (not a file). Whenever you press Ctrl+V, it inserts that content (which is text) to a current open file which has a focus.

I have an app for catching a global hotkey. Note this is not a window application, it's a console one and it catches the hotkey globally. Let's say I have the hotkey of Ctrl+U. So what I want to do is when I press Ctrl+U I want to insert some predefined text to a current open file. Just like Ctrl+V does! The differences from a standard Ctrl+V is that I want to insert a predefined text and the hotkey is different.

How do I do this?

I'd prefer a cross-platform solution, however first of all I'm going to do that for Linux, specifically Ubuntu. The language is not important but Java or Scala would be better. Of course, I understand that the solutions is Java uses native OS' API for that.

Was it helpful?

Solution

I'm hoping that this hackish solution would work, but it is still untested, I am unsure how to catch the event for the hotkey.

The idea behind this code is the following five steps:

  1. Get the old text in the clipboard and temporarily save it
  2. Paste our predefined text into the clipboard
  3. Trigger the global paste event
  4. Release the global paste event
  5. Reset the clipboard to the old text

This should give the appearance of a new clipboard (if not, hopefully it inspires you to come up with a better, less hackish solution).

Without further ado, here is my code. First I have a simple helper method to set the value of the clipboard (as we do this twice).

public static void setClipboard(String s) {
    StringSelection contents = new StringSelection(s);
    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    clipboard.setContents(contents, contents);
}

And then, I have a main method where I go through the five steps in order.

public static void main(String[] args) {

    // Step 1 ) get old text
    String oldText = "";
    try {
        oldText = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); 
    } catch (UnsupportedFlavorException ufe) {
        ufe.printStackTrace();
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }

    // Step 2 ) paste our text in clipboard
    setClipboard("This lorem ipsum predefined string blows my mind.");

    // Step 3 ) trigger paste event
    Robot robot = null;
    try {
        robot = new Robot();
    } catch (AWTException awte) {
        awte.printStackTrace();
    }
    robot.keyPress(KeyEvent.VK_CONTROL);
    robot.keyPress(KeyEvent.VK_V);

    // Step 4 ) Release paste event
    robot.keyRelease(KeyEvent.VK_CONTROL);
    robot.keyRelease(KeyEvent.VK_V);

    // Step 5 ) Reset clipboard
    setClipboard(oldText);

}

[Edit]:

Here is some code to test what kind of contents are in the Clipboard - image, text, etc. The unicode error was coming from the fact that the old contents of the clipboard were something that couldn't be represented by a plain String. To fix this error, you will have to check if the old contents were an image, the old contents were text, and save them accordingly.

public static int kindOfContents() {
    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    Transferable contents = clipboard.getContents(null);

    if(contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
        // String, save temporarily as string and write back as string
        return 0;
    } else if(contents.isDataFlavorSupported(DataFlavor.imageFlavor)) {
        // Image, save temporarily as BufferedImage and write back as image
        return 1;
    } else if(contents.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
        // List of files, save temporarily as java.util.List interface and write back as the file lists
        return 2;
    }

}

If the contents are text, then for saving and writing the content you would use the old method, repasted below for convenience.

// Step 1 ) get old text
String oldText = "";
try {
    oldText = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); 
} catch (UnsupportedFlavorException ufe) {
    ufe.printStackTrace();
} catch (IOException ioe) {
    ioe.printStackTrace();
}

// Step 5 ) Reset clipboard
setClipboard(oldText);

However, if the contents are an image, then for saving temporarily and rewriting you need to do the following. Note that the code for writing the image is not mine, but is taken from the accepted answer at Setting images to Clipboard - Java

// Step 1 ) get old image
BufferedImage img = null;
try {
    img = (BufferedImage) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.imageFlavor);
} catch (UnsupportedFlavorException ufe) {
    ufe.printStackTrace();
} catch (IOException ioe) {
    ioe.printStackTrace();
}

Taken from Setting images to Clipboard - Java :

// Step 5 ) Reset clipboard
ImageTransferable transferable = new ImageTransferable( image );
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(transferable, null);

static class ImageTransferable implements Transferable
{
    private Image image;

    public ImageTransferable (Image image)
    {
        this.image = image;
    }

    public Object getTransferData(DataFlavor flavor)
        throws UnsupportedFlavorException
    {
        if (isDataFlavorSupported(flavor))
        {
            return image;
        }
        else
        {
            throw new UnsupportedFlavorException(flavor);
        }
    }

    public boolean isDataFlavorSupported (DataFlavor flavor)
    {
        return flavor == DataFlavor.imageFlavor;
    }

    public DataFlavor[] getTransferDataFlavors ()
    {
        return new DataFlavor[] { DataFlavor.imageFlavor };
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top