Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java getting mouse location on multiple monitor environment

Tags:

java

screen

mouse

I have searched for a while on the internet but I didn't find any solution for my problem. I know that you can get the current mouse position with

PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();

The problem is in a multi environment screen I am just getting the mouse position relative to the main screen. Which means if the second screen is to the left of the main screen I receive for example X: -917.0 Location Y: -137.0. I know that these values depend on the screen resolution and the order of the monitors. Is there any possibility to obtain the mouse position on the current active screen?

Kind regards

like image 528
grill2010 Avatar asked Feb 05 '14 18:02

grill2010


1 Answers

Basically, what I did was take the PointerInfo and subtract the GraphicsDevice bounds from it, if the result was less the 0 (because the screen was left of the main screen), I multiplied the result by -1

The heart of the solution looks like this...

// Pointer info
PointerInfo pi = MouseInfo.getPointerInfo();
Point mp = pi.getLocation();
// The devices bounds
Rectangle bounds = getDeviceBounds(pi.getDevice());

// Create new "virtual" point based on the mouse point
virtualPoint = new Point(mp);
// Subtract the x/y position of the device
virtualPoint.x -= bounds.x;
virtualPoint.y -= bounds.y;
// Clip negative values...
if (virtualPoint.x < 0) {
    virtualPoint.x *= -1;
}
if (virtualPoint.y < 0) {
    virtualPoint.y *= -1;
}

The following example shows the actual desktop mouse position (as reported by MouseInfo) on the first line and the second line shows the "screen" position within the context of the GraphicsDevice

Where's my mouse

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class WheresMyMouse {

    public static void main(String[] args) {
        new WheresMyMouse();
    }

    public WheresMyMouse() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private double scale;
        private List<Rectangle> screenBounds;

        private Point virtualPoint;
        private Point screenPoint;

        public TestPane() {
            screenBounds = getScreenBounds();
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    PointerInfo pi = MouseInfo.getPointerInfo();
                    Point mp = pi.getLocation();
                    Rectangle bounds = getDeviceBounds(pi.getDevice());

                    screenPoint = new Point(mp);
                    virtualPoint = new Point(mp);
                    virtualPoint.x -= bounds.x;
                    virtualPoint.y -= bounds.y;
                    if (virtualPoint.x < 0) {
                        virtualPoint.x *= -1;
                    }
                    if (virtualPoint.y < 0) {
                        virtualPoint.y *= -1;
                    }
                    repaint();

                }
            });
            timer.start();
        }

        @Override
        public void invalidate() {
            super.invalidate();
            Rectangle virtualBounds = getVirtualBounds();
            scale = getScaleFactorToFit(virtualBounds.getSize(), getSize());
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int xOffset = 0;
            int yOffset = 0;
            List<Rectangle> scaledBounds = new ArrayList<>(screenBounds.size());
            for (Rectangle bounds : screenBounds) {
                bounds = scale(bounds);
                scaledBounds.add(bounds);
                if (bounds.x < xOffset) {
                    xOffset = bounds.x;
                }
                if (bounds.y < yOffset) {
                    yOffset = bounds.y;
                }
            }
            if (xOffset < 0) {
                xOffset *= -1;
            }
            if (yOffset < 0) {
                yOffset *= -1;
            }
            for (Rectangle bounds : scaledBounds) {
                bounds.x += xOffset;
                bounds.y += xOffset;
                g2d.setColor(Color.DARK_GRAY);
                g2d.fill(bounds);
                g2d.setColor(Color.GRAY);
                g2d.draw(bounds);
            }

            FontMetrics fm = g2d.getFontMetrics();

            g2d.setColor(Color.WHITE);
            if (screenPoint != null) {
                int x = 0;
                int y = fm.getAscent();

                g2d.drawString(screenPoint.toString(), x, y);
                screenPoint.x += xOffset;
                screenPoint.y += yOffset;
                screenPoint.x *= scale;
                screenPoint.y *= scale;
                g2d.fillOval(screenPoint.x - 2, screenPoint.y - 2, 4, 4);
            }

            if (virtualPoint != null) {
                int x = 0;
                int y = fm.getAscent() + fm.getHeight();

                g2d.drawString(virtualPoint.toString(), x, y);
            }

            g2d.dispose();
        }

        protected Rectangle scale(Rectangle bounds) {
            Rectangle scaled = new Rectangle(bounds);
            scaled.x *= scale;
            scaled.y *= scale;
            scaled.width *= scale;
            scaled.height *= scale;
            return scaled;
        }
    }

    public static Rectangle getScreenBoundsAt(Point pos) {
        GraphicsDevice gd = getGraphicsDeviceAt(pos);
        Rectangle bounds = null;
        if (gd != null) {
            bounds = gd.getDefaultConfiguration().getBounds();
        }
        return bounds;
    }

    public List<Rectangle> getScreenBounds() {

        List<Rectangle> bounds = new ArrayList<>(25);

        GraphicsDevice device = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice lstGDs[] = ge.getScreenDevices();

        ArrayList<GraphicsDevice> lstDevices = new ArrayList<GraphicsDevice>(lstGDs.length);
        for (GraphicsDevice gd : lstGDs) {
            GraphicsConfiguration gc = gd.getDefaultConfiguration();
            Rectangle screenBounds = gc.getBounds();
            bounds.add(screenBounds);
        }

        return bounds;
    }

    public static Rectangle getDeviceBounds(GraphicsDevice device) {

        GraphicsConfiguration gc = device.getDefaultConfiguration();
        Rectangle bounds = gc.getBounds();
        return bounds;
    }

    public static GraphicsDevice getGraphicsDeviceAt(Point pos) {

        GraphicsDevice device = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice lstGDs[] = ge.getScreenDevices();

        ArrayList<GraphicsDevice> lstDevices = new ArrayList<GraphicsDevice>(lstGDs.length);
        for (GraphicsDevice gd : lstGDs) {
            Rectangle screenBounds = getDeviceBounds(gd);
            if (screenBounds.contains(pos)) {
                lstDevices.add(gd);
            }
        }
        if (lstDevices.size() == 1) {
            device = lstDevices.get(0);
        }

        return device;

    }

    public static Rectangle getVirtualBounds() {

        Rectangle bounds = new Rectangle(0, 0, 0, 0);
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice lstGDs[] = ge.getScreenDevices();
        for (GraphicsDevice gd : lstGDs) {
            bounds.add(getDeviceBounds(gd));
        }
        return bounds;

    }

    public static double getScaleFactor(int iMasterSize, int iTargetSize) {

        double dScale = 1;
        dScale = (double) iTargetSize / (double) iMasterSize;

        return dScale;

    }

    public static double getScaleFactorToFit(Dimension original, Dimension toFit) {

        double dScale = 1d;
        if (original != null && toFit != null) {
            double dScaleWidth = getScaleFactor(original.width, toFit.width);
            double dScaleHeight = getScaleFactor(original.height, toFit.height);
            dScale = Math.min(dScaleHeight, dScaleWidth);
        }
        return dScale;

    }

}
like image 145
MadProgrammer Avatar answered Oct 04 '22 16:10

MadProgrammer