/* * Copyright 2008 Perry Nguyen * * Licensed under the GPLv2 */ package com.hanhuy.clipboard; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.Transferable; import java.awt.Toolkit; import javax.swing.JFrame; import javax.swing.JTextArea; import javax.swing.JScrollPane; import javax.swing.ScrollPaneConstants; import java.awt.SystemTray; import java.awt.TrayIcon; import java.awt.EventQueue; import java.net.ServerSocket; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.Socket; import javax.swing.JOptionPane; import javax.swing.ImageIcon; import java.awt.PopupMenu; import java.awt.MenuItem; import java.awt.AWTException; import java.awt.Frame; import java.awt.Font; import java.net.InetAddress; public class Main { private final Clipboard cb; private final JTextArea text; private final JFrame frame; private TrayIcon trayIcon; private SystemTray tray; private String lastSelection; public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { new Main(); } }); } Main() { cb = Toolkit.getDefaultToolkit().getSystemClipboard(); frame = new JFrame("Clipboard Listener"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); text = new JTextArea(10, 80); text.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); text.setEditable(false); JScrollPane pane = new JScrollPane(text, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); ImageIcon icon = new ImageIcon( getClass().getClassLoader().getResource( "com/hanhuy/clipboard/paste_plain.png")); frame.setIconImage(icon.getImage()); frame.add(pane); frame.pack(); frame.setVisible(true); Thread t = new Thread(new Runnable() { public void run() { ServerSocket server = null; try { server = new ServerSocket(4573); while (true) { Socket socket = server.accept(); try { InputStream in = socket.getInputStream(); InputStreamReader reader = new InputStreamReader(in); StringBuilder b = new StringBuilder(); char[] buf = new char[8192]; int read; while ((read = reader.read(buf, 0, 8192)) != -1) { b.append(buf, 0, read); } reader.close(); copyToClipboard(b.toString()); } catch (IOException e) { error(e.getMessage()); } finally { if (socket != null) { try { socket.close(); } catch (IOException ex) { } // ignore } } } } catch (IOException e) { error(e.getMessage()); } finally { if (server != null) { try { server.close(); } catch (IOException ex) { } // ignore } } } }, "Socket Listener/Reader"); t.setDaemon(true); t.start(); initSystemTray(icon); } private void initSystemTray(ImageIcon icon) { if (SystemTray.isSupported()) { tray = SystemTray.getSystemTray(); ActionListener l = new ActionListener() { public void actionPerformed(ActionEvent e) { if (!frame.isVisible()) { frame.setVisible(true); frame.setState(Frame.NORMAL); EventQueue.invokeLater(new Runnable() { public void run() { text.setText(lastSelection); text.setCaretPosition(0); } }); } else { frame.requestFocusInWindow(); frame.toFront(); } } }; PopupMenu popup = new PopupMenu(); MenuItem item = new MenuItem("Open Clipboard Listener Window"); item.addActionListener(l); popup.add(item); trayIcon = new TrayIcon(icon.getImage(), "Clipboard Listener", popup); trayIcon.addActionListener(l); try { tray.add(trayIcon); frame.addWindowListener(new WindowAdapter() { @Override public void windowIconified(WindowEvent e) { frame.setVisible(false); } @Override public void windowClosing(WindowEvent e) { tray.remove(trayIcon); } }); } catch (AWTException e) { error(e.getMessage()); } } } void copyToClipboard(final String selection) { Runnable r = new Runnable() { public void run() { StringSelection s = new StringSelection(selection); cb.setContents(s, s); // make sure this happens after clipboardChanged EventQueue.invokeLater(new Runnable() { public void run() { lastSelection = selection; if (!frame.isVisible() && trayIcon != null) { trayIcon.displayMessage("Clipboard Updated", selection, TrayIcon.MessageType.INFO); } else { text.setText(selection); text.setCaretPosition(0); } } }); } }; invokeOnEDT(r); } void clipboardChanged() { Runnable r = new Runnable() { public void run() { text.setText(""); lastSelection = ""; } }; invokeOnEDT(r); } private class StringSelection extends java.awt.datatransfer.StringSelection { StringSelection(String s) { super(s); } @Override public void lostOwnership(Clipboard cb, Transferable t) { super.lostOwnership(cb, t); clipboardChanged(); } } void error(final String error) { Runnable r = new Runnable() { public void run() { JOptionPane.showMessageDialog(frame, error); } }; invokeOnEDT(r); } void invokeOnEDT(Runnable r) { if (!EventQueue.isDispatchThread()) EventQueue.invokeLater(r); else r.run(); } }