解决方案
如果我们希望用户不使用元键拖动条目,我们应该始终允许system-default在拖放结束时进行拖动操作。在 Windows 上,这恰好是一个 DND.DRAG_MOVE 操作(我相信对于其他平台也是如此)。
source.addDragSupport(DND.DROP_MOVE, new Transfer[] { DragSelectionListener.getTransfer() }, new DragSelectionListener(viewer));
target.addDropSupport(DND.DROP_MOVE, new Transfer[]{ DropListListener.getTransfer() }, new DropListListener(viewer));
说明
三组操作应该相交:
- 允许拖动源的操作(使用 StructuredViewer.addDragSupport() 设置)
- 拖动目标支持的操作(使用 StructuredViewer.addDropSupport() 设置)
- 用户选择的操作(取决于放置时按下了哪些元键)
只有这样放置目标才会验证接收到的放置,并且会请求拖动源获取数据。
调查
元键的处理在org.eclipse.swt.dnd.DropTarget.setEventData()这一行完成
operations[0] = osToOp(operations[0]) & style;
if (operations[0] == DND.DROP_NONE) return false;
来自 droptarget 的样式与来自系统 drop 操作的值相交是基于 dragsource 但剥夺了DND.DRAG_DEFAULT。如果这两者不相交,则中止操作。
再往下,该集合与根据按下的元键计算的集合进行比较。操作可能会再次中止。
if ((operation & operations[0]) == 0) operation = DND.DROP_NONE;
可以通过将DND.DROP_DEFAULT 传递给addDropSupport() 来控制此行为,但更糟糕的是,用户选择的操作将与DND.DROP_MOVE 进行比较,如果不用作@ 的参数,则会更早过滤掉987654330@.
我认为DND.DROP_DEFAULT 的处理方式已被破坏,不应依赖。如果第一个条件有效地阻止了它就可以使用。