当存在Drag Source时,MouseUp事件直到MouseUp才会传递

Tor*_*bye 17 swt eclipse-rcp

我有一个老鼠听众.它有一些代码来响应mouseUp和mouseDown事件.这工作正常.

但是,只要我添加一个DragSource,我的mouseDown事件就不再发送 - 直到我释放鼠标按钮!

重现这一点很简单 - 下面是一个简单的程序,它包含一个只有鼠标监听器和拖动监听器的普通shell.当我运行它(在Mac上),然后按住鼠标按钮时,没有任何反应 - 但是一旦我释放鼠标按钮,我立即看到鼠标按下和鼠标按下事件.如果我注释掉拖动源,那么鼠标事件将以它们应该的方式传递.

我搜索过其他有类似问题的人,而我最接近解释的是:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=26605#c16 "如果您挂钩拖动检测,操作系统需要吃掉鼠标事件,直到它确定您是否已拖动."

但是,我不明白为什么这是真的 - 为什么操作系统必须吃掉鼠标事件以确定我是否有阻力?在我按下按钮的鼠标移动事件之前,拖动才会开始.

更重要的是:有人可以建议解决方法吗?(当我按下鼠标时,我尝试动态添加和删除我的拖动源,但是我无法通过拖放操作正常,因为它从未看到初始按键 - 我找不到以编程方式启动的方法拖动.)

这是示例程序:

    package swttest;

    import org.eclipse.swt.dnd.DND;
    import org.eclipse.swt.dnd.DragSource;
    import org.eclipse.swt.dnd.DragSourceEvent;
    import org.eclipse.swt.dnd.DragSourceListener;
    import org.eclipse.swt.events.MouseEvent;
    import org.eclipse.swt.events.MouseListener;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Shell;

    public class SwtTest {
        public static void main(String[] args) {
            final Display display = new Display();
            final Shell shell = new Shell(display);
            shell.addMouseListener(new MouseListener() {
                public void mouseUp(MouseEvent e) {
                    System.out.println("mouseUp");
                }

                public void mouseDown(MouseEvent e) {
                    System.out.println("mouseDown");
                }

                public void mouseDoubleClick(MouseEvent e) {
                    System.out.println("mouseDoubleClick");
                }
            });
            DragSourceListener dragListener = new DragSourceListener() {

                public void dragFinished(DragSourceEvent event) {
                    System.out.println("dragFinished");

                }

                public void dragSetData(DragSourceEvent event) {
                    System.out.println("dragSetData");

                }

                public void dragStart(DragSourceEvent event) {
                    System.out.println("dragStart");
                }
            };
            DragSource dragSource = new DragSource(shell, DND.DROP_COPY | DND.DROP_MOVE);
            dragSource.addDragListener(dragListener);
            shell.pack();
            shell.open();
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch())
                    display.sleep();
            }
            display.dispose();
        }
    }
Run Code Online (Sandbox Code Playgroud)

Sco*_* K. 8

要回答你关于为什么会发生这种情况的具体问题 - 在Cocoa上,我们不会考虑在鼠标移动几个像素之前开始拖动.如果你匆匆点击,这可以确保防止"意外"拖延.在Linux和Win32上,窗口工具包可以进行拖动检测.如果您只是按住按钮,则检测超时并且鼠标按下.在Cocoa上我们没有时间,这就是为什么在检测到拖动或鼠标移动之前没有任何反应.

这是很多细节,但结论是行为不一致,我们应该始终能够立即交付鼠标,而无需等待拖动检测完成.

我没有看到解决方法,因为这是在Control看到事件之前发生的.

看到这个包含win32,gtk和cocoa SWT补丁的bug.