O problema com MouseMotionListener é que ele só retorna a posição do mouse se o mesmo se encontra em cima do componente em questão.
Fuçando a implementação do método Component.getMousePosition() vi que Java 1.5 vem com a classe MouseInfo com que dá para pegar a posição do mouse em qualquer lugar da tela (além de outras informações sobre o mouse).
http://java.sun.com/j2se/1.5.0/docs/api/java/awt/MouseInfo.html
[]s,
Sami
Ah, não pude resistir… uma implementação PoC rápido e tosco utilizando um JFrame com setDecorated(false):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class XEyes extends JFrame implements Runnable {
private static final int BORDER = 3;
private static final int EYE_DIAMETER = 22;
private static final int EYE_RADIUS = EYE_DIAMETER / 2;
private static final int PUPIL_DIAMETER = 8;
private static final int PUPIL_RADIUS = PUPIL_DIAMETER / 2;
private static final int EYE_DISTANCE = 10;
private static final int LEFT_EYE_X = EYE_RADIUS + BORDER;
private static final int LEFT_EYE_Y = EYE_RADIUS + BORDER;
private static final int RIGHT_EYE_X = LEFT_EYE_X + EYE_DIAMETER + EYE_DISTANCE;
private static final int RIGHT_EYE_Y = EYE_RADIUS + BORDER;
private final Cursor normalCursor;
private final Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR);
private Point lastPt = null;
private Point mouseDown = null;
private JPanel eyePanel;
public XEyes() {
super();
setUndecorated(true);
setAlwaysOnTop(true);
this.eyePanel = new JPanel() {
public void paint(Graphics g) {
paintEyes(g);
}
};
this.eyePanel.setPreferredSize(new Dimension(RIGHT_EYE_X + EYE_RADIUS + BORDER, LEFT_EYE_Y + EYE_RADIUS + BORDER));
normalCursor = this.eyePanel.getCursor();
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(eyePanel, BorderLayout.CENTER);
// allow dragging the window
this.eyePanel.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
eyePanel.setCursor(moveCursor);
mouseDown = e.getPoint();
}
public void mouseReleased(MouseEvent e) {
eyePanel.setCursor(normalCursor);
Point pt = e.getPoint();
pt.translate(-mouseDown.x, -mouseDown.y);
Point location = getLocation();
location.translate(pt.x, pt.y);
setLocation(location);
}
});
Thread t = new Thread(this);
t.start();
pack();
setVisible(true);
}
public static void main(String[] args) {
new XEyes();
}
public void paintEyes(Graphics g) {
if (this.lastPt == null) {
this.lastPt = MouseInfo.getPointerInfo().getLocation();
}
// graphics
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.clearRect(0, 0, this.eyePanel.getWidth(), this.eyePanel.getHeight());
Ellipse2D ellipse = new Ellipse2D.Double(LEFT_EYE_X - EYE_RADIUS, LEFT_EYE_Y - EYE_RADIUS, EYE_DIAMETER, EYE_DIAMETER);
g2.setColor(Color.BLACK);
g2.draw(ellipse);
float dx = lastPt.x - this.getX()- LEFT_EYE_X;
float dy = lastPt.y - this.getY() - LEFT_EYE_Y;
float dsize = Math.max(1, Math.max(Math.abs(dx), Math.abs(dy)));
dx *= (EYE_RADIUS - PUPIL_RADIUS - 1) / dsize;
dy *= (EYE_RADIUS - PUPIL_RADIUS - 1) / dsize;
Ellipse2D center = new Ellipse2D.Double(LEFT_EYE_X - PUPIL_RADIUS + dx, LEFT_EYE_Y - PUPIL_RADIUS + dy, PUPIL_DIAMETER, PUPIL_DIAMETER);
g2.fill(center);
ellipse = new Ellipse2D.Double(RIGHT_EYE_X - EYE_RADIUS, RIGHT_EYE_Y - EYE_RADIUS, EYE_DIAMETER, EYE_DIAMETER);
g2.setColor(Color.BLACK);
g2.draw(ellipse);
dx = lastPt.x - this.getX() - RIGHT_EYE_X;
dy = lastPt.y - this.getY() - RIGHT_EYE_Y;
dsize = Math.max(1, Math.max(Math.abs(dx), Math.abs(dy)));
dx *= (EYE_RADIUS - PUPIL_RADIUS - 1) / dsize;
dy *= (EYE_RADIUS - PUPIL_RADIUS - 1) / dsize;
center = new Ellipse2D.Double(RIGHT_EYE_X - PUPIL_RADIUS + dx, RIGHT_EYE_Y - PUPIL_RADIUS + dy, PUPIL_DIAMETER, PUPIL_DIAMETER);
g2.fill(center);
}
public void run() {
while(true) {
Point newPt = MouseInfo.getPointerInfo().getLocation();
// only paint if the mouse has moved
if (this.lastPt == null || !newPt.equals(this.lastPt)) {
this.lastPt = newPt;
this.eyePanel.repaint();
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}