MouseHook会在Mac OS X上删除文本

时间:2019-01-11 11:04:53

标签: java macos

我正在开发Java FX应用程序,其中涉及使用moushook捕获用鼠标选择的文本。在使用Java 8编译和运行时,此方法可以正常工作,但是当前需要使用Java 10,这在Mac OS X上引起了问题(在Windows 10上运行时没有问题)。

问题在于,当从文档中选择文本时(例如TexEdit中的文本),所选文本将被删除并替换为“ c”,而不是被复制。这种情况并非每次都发生,但会经常发生。

我将mouseHook类简化为一个显示问题的非常基本的测试用例:

MouseHook类--------------------------------------------- ------------

package problem;

import org.jnativehook.GlobalScreen;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;

import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;

    public class MouseHook implements NativeMouseInputListener
    {
        private static MouseHook mouseHook = null;

        private Robot mouseRobot = null;

        private boolean mouseLeftButtonDown = false;
        private boolean dragged = false;

        private MouseHook()
        {
            //disable console output from JNativeHook's internal logger (mouse-tracking, etc)
            java.util.logging.Logger logger = java.util.logging.Logger.getLogger(GlobalScreen.class.getPackage().getName());
            logger.setLevel(java.util.logging.Level.OFF);
        }

        public static synchronized MouseHook getInstance()
        {
            if(mouseHook == null)
            {
                mouseHook = new MouseHook();

                GlobalScreen.addNativeMouseListener(mouseHook);
                GlobalScreen.addNativeMouseMotionListener(mouseHook);
            }

            return mouseHook;
        }

        @Override
        public void nativeMousePressed(NativeMouseEvent e)
        {
            //If left button pressed, set mouseLeftButtonDown and look-out for dragging
            if(e.getButton() == NativeMouseEvent.BUTTON1)
            {
                mouseLeftButtonDown = true;
            }
        }

        @Override
        public void nativeMouseDragged(NativeMouseEvent e)
        {
            //only record a drag if left mouse button is held down.
            //NativeMouseEvent doesn't say which button was the source, hence test the variable.
            if(mouseLeftButtonDown)
            {
                dragged = true;
            }
        }

        @Override
        public void nativeMouseReleased(NativeMouseEvent e)
        {
            //copy text if the mouse was dragged while the left mouse button was held down.
            if(e.getButton() == NativeMouseEvent.BUTTON1)
            {
                final Timer timer = new Timer("ReleaseDetect");

                timer.schedule(new TimerTask()
                {
                    @Override
                    public void run()
                    {
                        if(dragged)
                        {
                            copy();
                            dragged = false;
                        }

                        mouseLeftButtonDown = false;

                        timer.cancel();
                    }
                }, 500);
            }
        }

        @Override
        public void nativeMouseClicked(NativeMouseEvent e)
        {}

        @Override
        public void nativeMouseMoved(NativeMouseEvent e)
        {}

        private synchronized void copy()
        {
            try
            {
                if(mouseRobot == null)
                {
                    mouseRobot = new Robot();

                    mouseRobot.setAutoDelay(100);
                    mouseRobot.setAutoWaitForIdle(true);
                }

                if(System.getProperty("os.name").toLowerCase().contains("mac"))
                {
                    mouseRobot.keyPress(KeyEvent.VK_META);
                    mouseRobot.keyPress(KeyEvent.VK_C);
                    mouseRobot.keyRelease(KeyEvent.VK_C);
                    mouseRobot.keyRelease(KeyEvent.VK_META);
                }
                else
                {
                    mouseRobot.keyPress(KeyEvent.VK_CONTROL);
                    mouseRobot.keyPress(KeyEvent.VK_C);
                    mouseRobot.keyRelease(KeyEvent.VK_C);
                    mouseRobot.keyRelease(KeyEvent.VK_CONTROL);
                }

                Thread.sleep(250);

                Transferable t=Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);

                if(t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor))
                {
                    String activeContent = (String) t.getTransferData(DataFlavor.stringFlavor);
                    System.out.println(activeContent);
                }
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }

运行示例的类------------------------------------------ --------------

package problem;

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;

public class Runnit
{
    private static MouseHook mouseHook;

    public static void main(String[] args)
    {
        try
        {
            GlobalScreen.registerNativeHook();
        }
        catch(NativeHookException e)
        {
            System.out.println("Cannot set up the NativeHook listener on the GlobalScreen");
        }

        mouseHook = MouseHook.getInstance();
    }
}

我正在使用Oracle的Java 10.0.2和jNativeHook 2.1.0,以及在Mac mini上使用Mac OS High Sierra(10.13.6)。

问题似乎出在使用java.awt.Robot,而不是jNativeHook。

例如如果我将VK_C keyPress / Release替换为VK_B,则鼠标钩会删除所选文本并将其替换为“ b”。

我的直觉是VK_META按键被忽略了。我尝试在按键之前延迟一下,但这没什么区别。

我也尝试过使用其他鼠标和其他人的Macintosh,但是问题仍然存在。就像我说的那样,只有在使用Java 10编译并运行代码的情况下,它才会在Mac OS X而不是Windows 10上发生。

如果有人对这是一个失败的原因,或者有解决方法的任何想法,我将不胜感激。可能是因为我通常在Windows上工作并且对Mac OS X不太了解,所以错过了一些明显的事情。

0 个答案:

没有答案