JBR-9591 Wayland: Fix wrong DnD action on KWin

This patch implements a workaround for a bug that exists on KWin 6.5. For
some reason, KWin sends a wl_data_source.action(0) event immediately
after wl_data_source.dnd_drop_finished(). This makes the drag source
think that the DnD operation failed, even though it succeeded.
The workaround it to ignore the wl_data_source.action() events
after a successful wl_data_source.dnd_drop_finished()

In addition to this, this patch also fixes some inconsistency with
translating between AWT and Wayland DnD operation masks. This doesn't
have any visible effect though, since the mask values happen to be the
same.
This commit is contained in:
Nikita Tsarev
2025-11-14 12:17:42 +01:00
committed by jbrbot
parent 23febad80e
commit 0157189e36
2 changed files with 19 additions and 9 deletions

View File

@@ -61,7 +61,14 @@ public class WLDragSourceContextPeer extends SunDragSourceContextPeer {
@Override
protected synchronized void handleDnDAction(int action) {
this.action = action;
// This if statement is a workaround for a KWin bug.
// KWin 6.5.1 may send an additional action(0) after dnd_drop_performed().
// Spec says that after dnd_drop_performed(), no further action() events will be sent,
// except for maybe action(dnd_ask), but since we do not announce support for dnd_ask,
// we don't need to worry about it.
if (!didSucceed) {
this.action = action;
}
}
@Override

View File

@@ -70,7 +70,7 @@ public class WLDropTargetContextPeer extends SunDropTargetContextPeer {
int dropAction = 0;
if (hasTarget() && event != MouseEvent.MOUSE_EXITED) {
dropAction = currentOffer.getSelectedAction();
dropAction = WLDataDevice.waylandActionsToJava(currentOffer.getSelectedAction());
}
postDropTargetEvent(
@@ -115,17 +115,20 @@ public class WLDropTargetContextPeer extends SunDropTargetContextPeer {
return;
}
int actions = 0;
int javaActions = 0;
if (hasTarget()) {
actions = WLDataDevice.javaActionsToWayland(getTargetActions());
javaActions = getTargetActions();
}
int preferredAction = SunDragSourceContextPeer.convertModifiersToDropAction(WLToolkit.getInputState().getModifiers(), actions);
int javaPreferredAction = SunDragSourceContextPeer.convertModifiersToDropAction(WLToolkit.getInputState().getModifiers(), javaActions);
if (actions != lastActions || preferredAction != lastPreferredAction) {
currentOffer.setDnDActions(actions, preferredAction);
lastActions = actions;
lastPreferredAction = preferredAction;
int waylandActions = WLDataDevice.javaActionsToWayland(javaActions);
int waylandPreferredAction = WLDataDevice.javaActionsToWayland(javaPreferredAction);
if (waylandActions != lastActions || waylandPreferredAction != lastPreferredAction) {
currentOffer.setDnDActions(waylandActions, waylandPreferredAction);
lastActions = waylandActions;
lastPreferredAction = waylandPreferredAction;
}
}