-
Bug
-
Resolution: External
-
P4
-
None
-
17
-
x86_64
-
linux_ubuntu
ADDITIONAL SYSTEM INFORMATION :
openjdk version "17.0.11" 2024-04-16
OpenJDK Runtime Environment Temurin-17.0.11+9 (build 17.0.11+9)
OpenJDK 64-Bit Server VM Temurin-17.0.11+9 (build 17.0.11+9, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
Dragging and dropping with a simple program using the notion window manager often fails. Sometimes the cursor will report that dropping is not possible. Other times the drop will actually go to the window behind it.
I initially filed this bug with my window manager because I assumed it was a bug there.
However, after debugging further, I believe that the JDK's implementation of identifying the XDnD target window is flawed, and notion happens to trigger this because it adds a lot of windows to the hierarchy.
In short, sun.awt.X11.XDragSourceContextPeer.updateTargetWindow appears to identify a child of the root window that the cursor is in. In my case, this is a "WScreen" in notion. From there, sun.awt.X11.XDragSourceContextPeer.findClientWindow() searches children until it finds one that is not hidden. In my case, this is finding a window that is "iconified" and not in focus.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Use notion window manager
2. Run below program
3. Open a program that can receive drops and place it behind the program
4. Attempt to drag text from the top frame to the bottom
5. Observe it fail OR go to the program behind it
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I was expecting the dropped data to go to the active window.
ACTUAL -
In some cases, the drop will fail (the cursor indicates dropping is not possible). In others, it will succeed but the dropped text will go to the window behind. I have observed a few times the text correctly dropping into the Java frame. I think the non-determinism comes from sun.awt.X11.XDragSourceContextPeer.findClientWindow()
---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
public class DragAndDropExample extends JFrame {
public DragAndDropExample() {
setTitle("Drag and Drop Example");
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
JTextArea sourceTextArea = new JTextArea("Drag this text");
sourceTextArea.setDragEnabled(true);
sourceTextArea.setLineWrap(true);
sourceTextArea.setWrapStyleWord(true);
JScrollPane sourceScrollPane = new JScrollPane(sourceTextArea);
JTextArea targetTextArea = new JTextArea("Drop here");
targetTextArea.setLineWrap(true);
targetTextArea.setWrapStyleWord(true);
JScrollPane targetScrollPane = new JScrollPane(targetTextArea);
new DropTarget(targetTextArea, new DropTargetListener() {
@Override
public void dragEnter(DropTargetDragEvent dtde) {
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
dtde.acceptDrag(DnDConstants.ACTION_COPY);
System.out.println("Drag Enter: Data flavor supported");
} else {
dtde.rejectDrag();
System.out.println("Drag Enter: Data flavor not supported");
}
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
// No action needed here
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
// No action needed here
}
@Override
public void dragExit(DropTargetEvent dte) {
System.out.println("Drag Exit");
}
@Override
public void drop(DropTargetDropEvent dtde) {
try {
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
dtde.acceptDrop(DnDConstants.ACTION_COPY);
String droppedText = (String) dtde.getTransferable().getTransferData(DataFlavor.stringFlavor);
targetTextArea.append(droppedText);
dtde.dropComplete(true);
System.out.println("Drop: Success");
} else {
dtde.rejectDrop();
System.out.println("Drop: Data flavor not supported");
}
} catch (Exception ex) {
ex.printStackTrace();
dtde.dropComplete(false);
System.out.println("Drop: Exception occurred");
}
}
});
setLayout(new GridLayout(2, 1));
add(sourceScrollPane);
add(targetScrollPane);
}
public static void main(String[] args) {
Logger platformLogger = Logger.getLogger("sun.awt.X11.xembed.xdnd.XDnDDropSourceProtocol");
platformLogger.setLevel(Level.ALL);
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.ALL);
platformLogger.addHandler(consoleHandler);
SwingUtilities.invokeLater(() -> {
new DragAndDropExample().setVisible(true);
});
}
}
---------- END SOURCE ----------
FREQUENCY : often
openjdk version "17.0.11" 2024-04-16
OpenJDK Runtime Environment Temurin-17.0.11+9 (build 17.0.11+9)
OpenJDK 64-Bit Server VM Temurin-17.0.11+9 (build 17.0.11+9, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
Dragging and dropping with a simple program using the notion window manager often fails. Sometimes the cursor will report that dropping is not possible. Other times the drop will actually go to the window behind it.
I initially filed this bug with my window manager because I assumed it was a bug there.
However, after debugging further, I believe that the JDK's implementation of identifying the XDnD target window is flawed, and notion happens to trigger this because it adds a lot of windows to the hierarchy.
In short, sun.awt.X11.XDragSourceContextPeer.updateTargetWindow appears to identify a child of the root window that the cursor is in. In my case, this is a "WScreen" in notion. From there, sun.awt.X11.XDragSourceContextPeer.findClientWindow() searches children until it finds one that is not hidden. In my case, this is finding a window that is "iconified" and not in focus.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Use notion window manager
2. Run below program
3. Open a program that can receive drops and place it behind the program
4. Attempt to drag text from the top frame to the bottom
5. Observe it fail OR go to the program behind it
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I was expecting the dropped data to go to the active window.
ACTUAL -
In some cases, the drop will fail (the cursor indicates dropping is not possible). In others, it will succeed but the dropped text will go to the window behind. I have observed a few times the text correctly dropping into the Java frame. I think the non-determinism comes from sun.awt.X11.XDragSourceContextPeer.findClientWindow()
---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
public class DragAndDropExample extends JFrame {
public DragAndDropExample() {
setTitle("Drag and Drop Example");
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
JTextArea sourceTextArea = new JTextArea("Drag this text");
sourceTextArea.setDragEnabled(true);
sourceTextArea.setLineWrap(true);
sourceTextArea.setWrapStyleWord(true);
JScrollPane sourceScrollPane = new JScrollPane(sourceTextArea);
JTextArea targetTextArea = new JTextArea("Drop here");
targetTextArea.setLineWrap(true);
targetTextArea.setWrapStyleWord(true);
JScrollPane targetScrollPane = new JScrollPane(targetTextArea);
new DropTarget(targetTextArea, new DropTargetListener() {
@Override
public void dragEnter(DropTargetDragEvent dtde) {
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
dtde.acceptDrag(DnDConstants.ACTION_COPY);
System.out.println("Drag Enter: Data flavor supported");
} else {
dtde.rejectDrag();
System.out.println("Drag Enter: Data flavor not supported");
}
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
// No action needed here
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
// No action needed here
}
@Override
public void dragExit(DropTargetEvent dte) {
System.out.println("Drag Exit");
}
@Override
public void drop(DropTargetDropEvent dtde) {
try {
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
dtde.acceptDrop(DnDConstants.ACTION_COPY);
String droppedText = (String) dtde.getTransferable().getTransferData(DataFlavor.stringFlavor);
targetTextArea.append(droppedText);
dtde.dropComplete(true);
System.out.println("Drop: Success");
} else {
dtde.rejectDrop();
System.out.println("Drop: Data flavor not supported");
}
} catch (Exception ex) {
ex.printStackTrace();
dtde.dropComplete(false);
System.out.println("Drop: Exception occurred");
}
}
});
setLayout(new GridLayout(2, 1));
add(sourceScrollPane);
add(targetScrollPane);
}
public static void main(String[] args) {
Logger platformLogger = Logger.getLogger("sun.awt.X11.xembed.xdnd.XDnDDropSourceProtocol");
platformLogger.setLevel(Level.ALL);
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.ALL);
platformLogger.addHandler(consoleHandler);
SwingUtilities.invokeLater(() -> {
new DragAndDropExample().setVisible(true);
});
}
}
---------- END SOURCE ----------
FREQUENCY : often