JDK-4218528 : DnD of components with enabled input methods hangs java
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.2.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_nt
  • CPU: x86
  • Submitted: 1999-03-09
  • Updated: 1999-12-07
  • Resolved: 1999-12-07
Related Reports
Duplicate :  
Description

Name: vi73552			Date: 03/09/99


Drag and Drop of components for which input methods are enabled
hangs java. A ``workaround'' for the sample source that follows
is to add a call 'enableInputMethods(false);' to the constructor
of 'DragLabel'. This isn't a solution, the example doesn't use
input, a real application will. (I'm having the same problem
with JTrees.) 

To reproduce:
start 'Hang'
drag a text string to another panel in the same window or
to another window (there are 2 windows) and drop it there.
Java will hang.

After the source some thread dumps obtained with JDB are included.

java full version "JDK-1.2-V"

source:
import java.awt.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;

import javax.swing.*;

class Hang extends JFrame
{
    Hang()
    {
	getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
    	getContentPane().add(new StringPanel());
    	getContentPane().add(new StringPanel());
    	pack();
    	setSize(100, 200);
    	show();
    }
    public static void main(String[] args)
    {
	    new Hang();
	    new Hang();
    }
}
class StringPanel extends JPanel implements DropTargetListener
{
    StringVec strings;
    DropTarget dropTarget;

    StringPanel()
    {
	setBorder(BorderFactory.createEtchedBorder());
    	strings = new StringVec();
    	strings.listeners.add(this);
    	strings.add("aap");
    	strings.add("noot");
    	strings.add("mies");
    	strings.add("wim");
    	strings.add("zus");
    	strings.add("jet");
		dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true);

    }
    void changed()
    {
    	strings.fill(this);
    	revalidate();
    	repaint();
    }
    public void dropActionChanged(DropTargetDragEvent dtde)
    {
        dragEnter(dtde);
    }
    public void dragEnter(DropTargetDragEvent dtde)
    {
        int dropAction = dtde.getDropAction();
        
        if (dropAction != DnDConstants.ACTION_COPY
        &&  dropAction != DnDConstants.ACTION_MOVE)
        {
            dtde.rejectDrag();
            
            return;
        }

        DataFlavor flavor[] = dtde.getCurrentDataFlavors();

        for (int i=0; i<flavor.length; i++)   
        {
            if	(flavor[i].equals(DragLabel.flavor))
            {
                dtde.acceptDrag(dropAction);

                return;
            }
        }

        dtde.rejectDrag();
    }
    public void dragOver(DropTargetDragEvent dtde){}
    public void dragScroll(DropTargetDragEvent dtde){}
    public void dragExit(DropTargetEvent dte){}
    public void drop(DropTargetDropEvent dtde)
    {
        int dropAction = dtde.getDropAction();
        
        Transferable transferable = dtde.getTransferable();
        DataFlavor flavors[] = dtde.getCurrentDataFlavors();
        String str = null;
        
        try
        {
            for (int i = 0; i < flavors.length; i++)
            {
                if (flavors[i].equals(DragLabel.flavor))
                {
                    str = (String) transferable.getTransferData(flavors[i]);
                }
            }
        }
        catch	(Throwable t)
        {
        }
        
        if (str == null)
        {
            dtde.rejectDrop();
            dtde.getDropTargetContext().dropComplete(true);
            
            return;
        }
        else
        {
			strings.add(str);
        }
        
        dtde.getDropTargetContext().dropComplete(true);
    }
}
class StringVec
{
   Vector vec = new Vector();
   Vector listeners = new Vector();

   synchronized void add(String str)
   {
   	vec.add(str);
   	doNotify();

   }
   synchronized void rm(String str)
   {
   	vec.remove(str);
   	doNotify();
   }
   void doNotify()
   {
       for (int i=0; i<listeners.size(); i++)
        {
            ((StringPanel) listeners.get(i)).changed();
        }
   }
   void fill(StringPanel panel)
   {
	panel.removeAll();

	for (int i=0; i<vec.size(); i++)
	{
		panel.add(new DragLabel((String) vec.get(i), panel));
	}
   }
}
class DragLabel extends JTextField implements DragGestureListener, DragSourceListener, Transferable
{
public static final DataFlavor flavor = new DataFlavor(DragLabel.class, "DragLabel");
	StringPanel panel;
	DropTarget dropTarget;

	DragLabel(String str, StringPanel panel)
	{
		super(str);
		setEditable(false);
		this.panel = panel;

		dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, panel, true);
		DragSource source = DragSource.getDefaultDragSource();
		source.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
	}
	// Interface DragSourceListener
	public void dropActionChanged(DragSourceDragEvent dsde){}
	public void dragEnter(DragSourceDragEvent dsde){}
	public void dragOver(DragSourceDragEvent dsde){}	
	public void dragGestureChanged(DragSourceDragEvent dsde){}	
	public void dragExit(DragSourceEvent dse){}	
	public void dragDropEnd(DragSourceDropEvent dsde)
	{
		if (dsde.getDropSuccess() 
		&& dsde.getDropAction() == DnDConstants.ACTION_MOVE
		)
		{
		    panel.strings.rm(getText());
		}
		else
		{
		    if (dsde.getDropAction() == DnDConstants.ACTION_MOVE)
		    {
			  //enableInputMethods(true);
		    }
		}

		panel.revalidate();
		panel.repaint();
	}	
	public void dragGestureRecognized(DragGestureEvent dge)
	{
		if (dge.getDragAction() == DnDConstants.ACTION_MOVE)
		{
		      //enableInputMethods(false);
		}

		dge.startDrag(null, this, this);
	}
	// Interface Transferable
	public DataFlavor[] getTransferDataFlavors()
	{
		DataFlavor[] flavors = new DataFlavor[1];
		
		flavors[0] = flavor;

		return flavors;
	}	
	public boolean isDataFlavorSupported(DataFlavor flavor)
	{
		return flavor.equals(flavor);
	}
	public Object getTransferData(DataFlavor flavor)
			throws UnsupportedFlavorException, IOException
	{    
		return getText();
	}
}
//////
output from jdb Hang:
Initializing jdb...
0xae:class(Hang)
> run
run Hang 
running ...
main[1] 
Current thread "main" died. Execution continuing...
> threads
Group Hang.main:
1. (java.awt.EventDispatchThread)0x102             AWT-EventQueue-0 running    
2. (sun.awt.PostEventQueue)0x104                   PostEventQueue-0 cond. waiti
3. (java.lang.Thread)0x105                         AWT-Windows      cond. waiti
4. (java.lang.Thread)0x106                         TimerQueue       cond. waiti
5. (sun.awt.ScreenUpdater)0x108                    Screen Updater   cond. waiti
6. (sun.awt.windows.WDragSourceContextPeer$1)0x10a Thread-1         running    
> where t@6
  [1] sun.awt.windows.WDragSourceContextPeer.doDragDrop (native method)
  [2] sun.awt.windows.WDragSourceContextPeer$1.run (WDragSourceContextPeer$1:163)
> where t@1
  [1] sun.awt.windows.WInputMethod.endCompositionNative (native method)
  [2] sun.awt.windows.WInputMethod.removeNotify (WInputMethod:246)
  [3] sun.awt.im.InputContext.removeNotify (InputContext:299)
  [4] java.awt.Component.removeNotify (Component:3421)
  [5] java.awt.Container.removeNotify (Container:1341)
  [6] javax.swing.JComponent.removeNotify (JComponent:3195)
  [7] javax.swing.text.JTextComponent.removeNotify (JTextComponent:1029)
  [8] java.awt.Container.removeAll (Container:428)
  [9] StringVec.fill (StringVec:148)
  [10] StringPanel.changed (StringPanel:49)
  [11] StringVec.doNotify (StringVec:143)
  [12] StringVec.rm (StringVec:137)
  [13] DragLabel.dragDropEnd (DragLabel:184)
  [14] java.awt.dnd.DragSourceContext.dragDropEnd (DragSourceContext:239)
  [15] sun.awt.windows.WDragSourceContextPeerDispatcher.run (WDragSourceContextPeerDispatcher:587)
  [16] javax.swing.SystemEventQueueUtilities.processRunnableEvent (SystemEventQueueUtilities:359)
  [17] javax.swing.SystemEventQueueUtilities.access$0 (SystemEventQueueUtilities:350)
  [18] javax.swing.SystemEventQueueUtilities$RunnableTarget.processEvent (SystemEventQueueUtilities$RunnableTarget:391)
  [19] java.awt.Component.dispatchEventImpl (Component:2376)
  [20] java.awt.Component.dispatchEvent (Component:2289)
  [21] java.awt.EventQueue.dispatchEvent (EventQueue:258)
  [22] java.awt.EventDispatchThread.run (EventDispatchThread:68)
>
(Review ID: 55247) 
======================================================================

Comments
EVALUATION The hanging no longer occurs on JDK1.3 build P. Most likely this was fixed when the deadlock bugs were fixed.
11-06-2004

WORK AROUND Name: vi73552 Date: 03/09/99 You could try to put calls to Component.enableInputMethods(false/true) throughout your code, but it's very hard to get it right. Maybe, the DnD code can do this (as a workaround). ======================================================================
11-06-2004