package tk.amberide.engine.input.awt; import java.awt.AWTEvent; import java.awt.AWTException; import java.awt.Component; import java.awt.Cursor; import java.awt.MouseInfo; import java.awt.Point; import java.awt.Robot; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.AWTEventListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.image.BufferedImage; import java.lang.ref.WeakReference; import java.util.HashSet; import java.util.Stack; import javax.swing.SwingUtilities; /** * * @author Tudor */ public class AWTMouse { private static final Stack<MouseEvent> events = new Stack<MouseEvent>(); private static MouseEvent currentEvent; private static HashSet<Integer> buttonDownBuffer = new HashSet<Integer>(); private static Point lastPoint = new Point(0, 0), grabEnter; private static WeakReference<Component> grabbedParent; private static AWTEventListener dispatch; private static int scroll; public static void create() { Toolkit.getDefaultToolkit().addAWTEventListener(dispatch = new AWTEventListener() { public void eventDispatched(AWTEvent e) { if (e instanceof MouseWheelEvent) { scroll -= ((MouseWheelEvent) e).getWheelRotation(); // TODO: check, this doesn't seem to work on all comps. } if (e != null && e.getSource() instanceof Component && ((Component) e.getSource()).equals(focused())) { if (e instanceof MouseEvent) { MouseEvent event = (MouseEvent) e; events.push(event); switch (event.getID()) { case MouseEvent.MOUSE_PRESSED: buttonDownBuffer.add(AWTInputMap.map(event)); break; case MouseEvent.MOUSE_RELEASED: buttonDownBuffer.remove(AWTInputMap.map(event)); break; } } } } }, AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_WHEEL_EVENT_MASK); } private static Component focused() { for (final Window w : Window.getWindows()) { if (w.isFocused()) { return w.getFocusOwner(); } } return null; } public static void destroy() { if (isCreated()) { Toolkit.getDefaultToolkit().removeAWTEventListener(dispatch); dispatch = null; events.clear(); buttonDownBuffer.clear(); grabbedParent = null; } } protected static void ensureCreated() { if (!isCreated()) { throw new IllegalStateException("AWTMouse is not created"); } } public static boolean isCreated() { return dispatch != null; } public static boolean isButtonDown(int button) { ensureCreated(); return buttonDownBuffer.contains(button); } public static boolean next() { if (!events.empty()) { currentEvent = events.pop(); return true; } currentEvent = null; return false; } public static int getEventX() { ensureCreated(); if (currentEvent != null) { return currentEvent.getX(); } return -1; } public static int getEventY() { ensureCreated(); if (currentEvent != null) { return currentEvent.getY(); } return -1; } public static int getDWheel() { ensureCreated(); int delta = scroll; scroll = 0; return delta; } public static int getEventButton() { ensureCreated(); if (currentEvent != null) { return AWTInputMap.map(currentEvent); } return 0; } public static boolean getEventButtonState() { ensureCreated(); if (currentEvent != null) { switch (currentEvent.getID()) { case MouseEvent.MOUSE_PRESSED: return true; case MouseEvent.MOUSE_RELEASED: return false; } } return false; } public static int getX() { return MouseInfo.getPointerInfo().getLocation().x; } public static int getY() { return MouseInfo.getPointerInfo().getLocation().y; } public static int getDX() { return MouseInfo.getPointerInfo().getLocation().x - lastPoint.x; } public static int getDY() { return -(MouseInfo.getPointerInfo().getLocation().y - lastPoint.y); } public static int getY(Component relative) { return relative.getHeight() - convert(MouseInfo.getPointerInfo().getLocation(), relative).y; // To OGL coords } public static int getX(Component relative) { return convert(MouseInfo.getPointerInfo().getLocation(), relative).x; } protected static Point convert(Point point, Component c) { SwingUtilities.convertPointFromScreen(point, c); return point; } public static void poll() { if (isGrabbed()) { Component parent = grabbedParent.get(); int threshold = Math.min((int) (parent.getWidth() - 5), (int) (parent.getHeight() - 5)); Point collision = new Point(lastPoint); SwingUtilities.convertPointFromScreen(collision, parent); if (collision.y <= threshold || collision.x <= threshold || collision.y >= parent.getHeight() - threshold || collision.x >= parent.getWidth() - threshold) { Point center = new Point(parent.getWidth() / 2, parent.getHeight() / 2); SwingUtilities.convertPointToScreen(center, parent); try { new Robot().mouseMove(center.x, center.y); } catch (AWTException ex) { ex.printStackTrace(); } } } lastPoint = MouseInfo.getPointerInfo().getLocation(); } public static int getButtonCount() { return MouseInfo.getNumberOfButtons(); } public static void setGrabbed(boolean grab) { for (final Window w : Window.getWindows()) { if (w.isFocused()) { if (grab) { Component parent = w.findComponentAt(convert(MouseInfo.getPointerInfo().getLocation(), w)); if (parent != null) { if (grabbedParent != null && grabbedParent.get() == parent) { return; } grabEnter = convert(MouseInfo.getPointerInfo().getLocation(), parent); parent.setCursor(Toolkit.getDefaultToolkit(). createCustomCursor(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB), new Point(0, 0), "blank cursor")); grabbedParent = new WeakReference<Component>(parent); w.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { setGrabbed(false); w.removeFocusListener(this); } }); } } else if (isGrabbed()) { Component parent = grabbedParent.get(); parent.setCursor(Cursor.getDefaultCursor()); try { SwingUtilities.convertPointToScreen(grabEnter, parent); new Robot().mouseMove(grabEnter.x, grabEnter.y); } catch (AWTException ex) { ex.printStackTrace(); } grabbedParent = null; grabEnter = null; } } } } public static boolean isGrabbed() { return grabbedParent != null && grabbedParent.get() != null; } }