In my SWT based application, I have a Canvas-derived custom Widget, which is displaying a bunch of "items". The whole purpose of these items is for the user to drag them out of the widget. I had no trouble implementing a DragSource, DragDetectListener and all that stuff to make DND work. The problem I am trying to solve is that I want the drag to be detected much earlier, i.e. after a much shorter mouse drag distance, than the default platform behavior.
I know I can override dragDetect() of the Widget class. However, this only allows me to veto the super class implementation, not to notif开发者_开发问答y that a drag already happened before the super class would think it has.
Basically, if I could generate the drag event myself, like if I could just use Widget.postEvent(SWT.DragDetect, eventWhichIAllocatedAndFilledOut) (which is package private), that would seem like my solution. I've looked at the code for drag detection in Widget, and it doesn't seem to be designed for this use-case. Is there a work around that let's me initiate drags anytime I want?
I have figured it out. It is possible to generate a custom event and distribute it to the DragDetect listener mechanism. The code below does the same as the internal implementation, but can be called at will from within the Widget implementation, for example from a MouseMoveListener's mouseMove(MouseEvent e) hook:
Event event = new Event();
event.type = SWT.DragDetect;
event.display = getDisplay();
event.widget = this;
event.button = e.button;
event.stateMask = e.stateMask;
event.time = e.time;
event.x = e.x;
event.y = e.y;
notifyListeners(SWT.DragDetect, event);
It is noteworthy that the built-in drag detection has to be disabled for this to work as intended. The default implementation is exposed via the dragDetect(MouseEvent e) method that can be called from a mouseDown() handler (as explained in the documentation for dragDetect()). It works by busy looping in the event thread until the drag is detected. It simply consumes mouse move events from the native event queue on the GTK backend at least. When a DragDetectListener is registered with the Widget, this will automatically be done, so unless one disables the mechanism via setDragDetect(false), a custom drag detection would only run after the built-in detection which imposes the delay because it is blocking the event thread, besides detecting the drag a second time, of course.
精彩评论