ARTICLE AD BOX
I've encountered a rather interesting problem. I wanted to extend my color-palette-viewer with the functionality to drag the colors into other applications. For a text editor this is easy, a Transferable with DataFlavor.stringFlavor is enough to get it working.
But there are color (chooser) buttons in various toolkits, for example theColorButton of GTK, and I'd like to be able to drag the colors to these color buttons, too. Text is not accepted by them, and to find out what format is accepted, I've simply dragged a color from the color button into my application to inspect that arriving data.
The DataFlavor in the drop is application/x-color; class=java.io.InputStream, which sounds nice enough, but getting the data from the drop yields the following exception:
java.io.IOException: Unsupported data format: 16 at sun.awt.X11.XSelection.getData(XSelection.java:415) at sun.awt.X11.XDnDDropTargetProtocol.getData(XDnDDropTargetProtocol.java:853) at sun.awt.X11.XDropTargetContextPeer.getNativeData(XDropTargetContextPeer.java:151) at sun.awt.dnd.SunDropTargetContextPeer.getTransferData(SunDropTargetContextPeer.java:264) at sun.awt.datatransfer.TransferableProxy.getTransferData(TransferableProxy.java:73) at java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(DropTargetContext.java:376) at ColorDropTestMain$1.drop(ColorDropTestMain.java:42) at java.awt.dnd.DropTarget.drop(DropTarget.java:455) at sun.awt.dnd.SunDropTargetContextPeer.processDropMessage(SunDropTargetContextPeer.java:538) at sun.awt.X11.XDropTargetContextPeer.processDropMessage(XDropTargetContextPeer.java:184) at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchDropEvent(SunDropTargetContextPeer.java:852) at sun.awt.dnd.SunDropTargetContextPeer$EventDispatcher.dispatchEvent(SunDropTargetContextPeer.java:776) at sun.awt.dnd.SunDropTargetEvent.dispatch(SunDropTargetEvent.java:48) at java.awt.Component.dispatchEventImpl(Component.java:4746) at java.awt.Container.dispatchEventImpl(Container.java:2294) at java.awt.Window.dispatchEventImpl(Window.java:2750) at java.awt.Component.dispatchEvent(Component.java:4713) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758) at java.awt.EventQueue.access$500(EventQueue.java:97) at java.awt.EventQueue$3.run(EventQueue.java:709) at java.awt.EventQueue$3.run(EventQueue.java:703) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.awt.EventQueue$4.run(EventQueue.java:731) at java.awt.EventQueue$4.run(EventQueue.java:729) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:728) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)The same happens when I drag a color from a Qt color button. This happens on JDK 8 and 21 alike. And the application/x-color flavor is the only one available in the drop. This is on a Linux with X11.
I've been looking at the JDK source code so far and it appears to be a limitation of the JVM/X11 bridge, but I'm not certain. The exception appears to be this one in sun.awt.X11.XSelection.getData(long, long), the preceding check has been in the JDK forever and hasn't been changed in 20 years as far as I can tell.
410: if (dataGetter.getActualFormat() != 8) { 411: throw new IOException("Unsupported data format: " + 412: dataGetter.getActualFormat()); 413: }Unfortunately my JDK and X11 knowledge is rather limited.
Is there any way that I can access the dropped data (without having to patch the JDK)? Did somebody else work with such drops before and knows how to get it to work?
Here is a simple example application which you can drag colors into:
import java.awt.datatransfer.DataFlavor; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import javax.swing.JFrame; import javax.swing.SwingUtilities; public final class ColorDropTestMain { public static final void main(String[] args) { SwingUtilities.invokeLater(() -> { JFrame dropFrame = new JFrame("Drop colors here"); dropFrame.setSize(800, 600); dropFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); new DropTarget(dropFrame, DnDConstants.ACTION_COPY_OR_MOVE, new DropTargetListener() { @Override public void dragEnter(DropTargetDragEvent dtde) { dtde.acceptDrag(DnDConstants.ACTION_COPY); } @Override public void dragExit(DropTargetEvent dte) { } @Override public void dragOver(DropTargetDragEvent dtde) { } @Override public void drop(DropTargetDropEvent dtde) { dtde.acceptDrop(DnDConstants.ACTION_COPY); for (DataFlavor dataFlavor : dtde.getCurrentDataFlavors()) { System.out.println(dataFlavor.getMimeType()); try { System.out.println(dtde.getTransferable().getTransferData(dataFlavor)) } catch (Throwable th) { th.printStackTrace(); } } dtde.dropComplete(true); } @Override public void dropActionChanged(DropTargetDragEvent dtde) { } }); dropFrame.setVisible(true); }); } }