Skip to content

dragListener events are duplicated and arrive in wrong order #3500

@ThomasH99

Description

@ThomasH99

Describe the bug
I've spend a few days to get to the bottom of this issue. My code implements a dragListener that didn't behave correctly but jumped back and forth. I long thought it was a problem in my own code, but in the end I discovered it is due to Component. pointerDragged(final Component lead, final int x, final int y, final Object currentPointerPress) duplicating events, which then arrive out of order, probably due to the order in which callSerially executes the submitted Runnables.

It seems the error is linked to the additional calls here

private void pointerDragged(final Component lead, final int x, final int y, final Object currentPointerPress)
...
        if (dragCallbacks < 2) {
                dragCallbacks++;
                Display.getInstance().callSerially(new Runnable() {
                    public void run() {
                        if (dragActivated) {
                            lead.pointerDragged(x, y, currentPointerPress);
                        }
                        dragCallbacks--;
                    }
                });
            }

To Reproduce
Run the below example code. Drag "DRAG ME" consistently upwards and you can see that many events arrive with a wrong y value, indicating (wrongly) that the drag direction has changed and that the received drag position has suddenly moved back to an earlier position like if the user's finger was jittering up and down.

int lastY = -1;
int dragDirection = 0; //0: init; -1=up; 1=down
int lastDragDirection = 0;
Form hi = new Form("Welcome", BoxLayout.y());

Label dragMe = new Label("DRAG ME");
dragMe.setDraggable(true);
dragMe.addDragOverListener((evt) -> {
    int y = evt.getY();
    lastDragDirection = dragDirection;
    if (lastY == -1 || y == lastY) { //ignore same y value
    } else if (y < lastY) {
        dragDirection = -1;
    } else if (y > lastY) {
        dragDirection = 1;
    }
    if (lastDragDirection != dragDirection) {
        Label dropTarget = evt.getDropTarget() instanceof Label ? (Label) evt.getDropTarget() : null;
        Log.p("Dragging " + (dragDirection == -1 ? "UP  " : dragDirection == 1 ? "DOWN" : "INIT") + " y= " + y + " d= " + (lastY - y)
                + (dropTarget != null ? " over " + dropTarget.getText() : ""));
    }
    lastY = y;
});
for (int i = 0; i < 20; i++) {
    if (i == 10) {
        hi.add(dragMe);
    }
    Label l = new Label("DropTarget " + i);
    l.setDropTarget(true);
    hi.add(l);
}
hi.show();

Expected behavior
The drag events should not duplicated, or if there is an important reason for doing it, it should be ensured they don't arrive out of order.

Desktop (please complete the following information):

  • OS: MacOS, Simulator

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions