JDK-4038721 : Win32:MouseDrag issues an event incorrectl
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.1,1.1.1,1.1.3,1.1.4
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS:
    generic,solaris_2.5.1,windows_95,windows_nt generic,solaris_2.5.1,windows_95,windows_nt
  • CPU: generic,other,x86
  • Submitted: 1997-03-13
  • Updated: 1998-08-13
  • Resolved: 1998-08-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other Other
1.1.5 1.1.5Fixed 1.2.0Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
>> From:	David Malkovsky <###@###.### <mailto:###@###.###>>
>> To:	"'Rob Clark (E-mail)'" <Rob.Clark@Eng>
>> Subject:	Imformation on an import regression in JDK 1.1.1 beta code
>> Date:	Wed, 12 Mar 1997 15:17:37 -0500
>> Mime-Version:	1.0
>> Content-Transfer-Encoding:	7bit
>> 
>> Rob,
>> 
>> The following report is from one of our senior developers on our IDE. 
>>  The problem he reports did not occur in JDK 1.1 but does happen with 
>> the code drop of  Feb 27 (JDK 1.1.1B win32 2_27).   As he notes in his 
>> description, this problem will be something our users will see almost 
>> immediately; they will drop a widget and when they try to move is 
>> final position with the mouse they will lose control on the widget. 
>>  Can you get his report to Amy Fowler?  Here is his description of the 
>> problem:
>> 
>> 
>> I have made changes that allow the 1.1.1 version of the JDK to be 
>> used. That said, however, I have to point out a problem that I have 
>> not seen before.  In a frame, create a button. Grab the move handle on 
>> the bottom and move up. If you do this slowly then the component will 
>> move. If, however, your mouse pointer ever moves over the button then 
>> the button quits moving and will not move again until you release the 
>> mouse button and start over. It is easier to see dragging on the 
>> bottom border but I have reproduced this behavior from the top border 
>> as well.
>> 
>> I have scanned the bug database and found 4034656 which appears to be 
>> the same bug. This bug is marked closed with no release specified 
>> which I assume means that it wasn't fixed. Is there anyway we can get 
>> additional info?  This problem is something our users will see almost 
>> immediately.
>> 
>> BugId: 4034656
>> Release Fixed: NULL
>> Priority: 1
>> State: closed
>> Submit Date: Feb 25 1997
>> Synopsis: Win32:MouseDrag issues an event incorrectly
>> Description: Click a mouse on a component derived either from Canva or 
>> Panel Class,
>> and drag the mouse out of the component (with the mouse being kept
>> pressed) so that the first drag event is issued outside the component. 
>> The drag event is issued not to the component where the mouse is
>> clicked first but to a component where the mouse is located. Or if
>> the mouse is released outside the component where it was pressed, a
>> MOUSE_RELEASED event is not issued.
>> 
>> David B. Malkovsky
>> SAS Institute Inc.
>> Email: ###@###.###
>> Phone: 919/677-8000, x7723; FAX:919/677-4444
>> 

Here is my code to test the problem. Sorry it is so long but it appears
to be related to the amount of time I am spending in the mouse routines:

import java.awt.*;
import java.awt.event.*;

class Test extends Frame
{
	Checkbox cbox = null;
	MouseHandler m = null;

	class MouseHandler implements MouseListener, MouseMotionListener,
WindowListener
	{
		Component mover = null;
		int moveType = 0;
		Point hitPoint = null;

		public void windowOpened(WindowEvent e) 
		{
		}
		public void windowClosing(WindowEvent e) 
		{
			System.exit(0);
		}
		public void windowClosed(WindowEvent e)
		{
		}
		public void windowIconified(WindowEvent e) 
		{
		}
		public void windowDeiconified(WindowEvent e) 
		{
		}
		public void windowActivated(WindowEvent e)
		{
		}
		public void windowDeactivated(WindowEvent e)
		{
		}
		public void mouseClicked(MouseEvent e)
		{
		}
		public void mousePressed(MouseEvent evt)
		{
			// walk through components and test the handles
			Component[] cList = getComponents();
			hitPoint = new Point(evt.getX(),evt.getY());
	
			//System.out.println("hitPoint:"+hitPoint);
			for(int i=0;i<cList.length;++i)
			{
				JHandle handle = new JHandle(cList[i]);
				moveType = handle.hitHandle(hitPoint.x, hitPoint.y);
				if (moveType != JHandle.noHit)
				{
					mover = cList[i];
					hitPoint.translate(-cList[i].getLocation().x,
-cList[i].getLocation().y);
					//System.out.println("hitPoint:"+hitPoint);
					return;
				}
			}

		}
		public void mouseReleased(MouseEvent e)
		{
		}
		public void mouseEntered(MouseEvent e)
		{
		}
		public void mouseExited(MouseEvent e)
		{
		}
		public void mouseDragged(MouseEvent evt)
		{
			if (mover != null)
			{
				int newHeight;
				int newWidth;
				Rectangle size = mover.getBounds();
				
				
				int x = evt.getX();
				int y = evt.getY();
				
				switch(moveType) 
				{
				case JHandle.moveHandle: // MOVE
					mover.setLocation(x - hitPoint.x, y - hitPoint.y);
					break;
				case JHandle.nwHandle: // NW anchor SE corner
					newWidth = size.x - (x - hitPoint.x);
					newHeight = size.y - (y - hitPoint.y);
					mover.setBounds(x - hitPoint.x, y - hitPoint.y,
						size.width+newWidth, size.height+newHeight);
					break;
				case JHandle.wHandle: // W  Anchor E side
					newWidth = size.x - (x - hitPoint.x);
					mover.setBounds(x - hitPoint.x, size.y,
						size.width+newWidth, size.height);
					break;
				case JHandle.swHandle: // SW Anchor NE corner
					newWidth = size.x - (x - hitPoint.x);
					newHeight = y - size.y;
					mover.setBounds(x - hitPoint.x, size.y,
						size.width+newWidth, newHeight);
					break;
				case JHandle.neHandle: // NE Anchor SW corner
					newWidth = x - size.x;
					newHeight = size.y - (y - hitPoint.y);
					mover.setBounds(size.x, y - hitPoint.y,
						newWidth, size.height+newHeight);
					break;
				case JHandle.eHandle: // E  Anchor W side
					newWidth = x - size.x;
					mover.setBounds(size.x, size.y,
						newWidth, size.height);
					break;
				case JHandle.seHandle: // SE Anchor NW corner
					newWidth = x - size.x;
					newHeight = y - size.y;
					mover.setBounds(size.x, size.y,
						newWidth, newHeight);
					break;
				case JHandle.nHandle: // N  Anchor S side
					newHeight = size.y - (y - hitPoint.y);
					mover.setBounds(size.x, y - hitPoint.y,
						size.width, size.height + newHeight);
					break;
				case JHandle.sHandle: // S  Anchor N side
					newHeight = y - size.y;
					mover.setBounds(size.x, size.y,
						size.width, newHeight);
					break;
				}
				repaint();
				
			}

		}
		public void mouseMoved(MouseEvent evt)
		{
			Cursor c = Cursor.getDefaultCursor();
			if (mover == null)
			{
				// walk through components and test the handles
				Component[] cList = getComponents();
				Point point = new Point(evt.getX(),evt.getY());

				
				for(int i=0;i<cList.length;++i)
				{
					JHandle handle = new JHandle(cList[i]);
					moveType = handle.hitHandle(point.x, point.y);
					Cursor tmpCursor = handle.handleCursor(moveType);
					if (tmpCursor.getType() != Cursor.DEFAULT_CURSOR)
					{
						setCursor(tmpCursor);
						return;
					}
				}
			}
			setCursor(c);
		}
	}
	public Test()
	{
		setBackground(Color.lightGray);
		m = new MouseHandler();
		addMouseListener(m);
		addMouseMotionListener(m);
		addWindowListener(m);
		setLayout(null);
		setSize(500,500);
		addNotify();
		cbox = new Checkbox("CheckBox");
		cbox.setBounds(30, 30, 60, 15);
		add(cbox);
		cbox.setVisible(true);
		show();
	}

	public void paint(Graphics g)
	{
		super.paint(g);
		Component[] c = getComponents();
		for(int i = 0;i<c.length;++i)
		{
			JHandle handle = new JHandle(c[i]);
			handle.paint(g);
		}
		
	}

	public static void main(String argv[])
	{
		Test t;
		t = new Test();
	}

}

class JHandle  
{
	public int x;
	public int y;
	int width;
	int height;
	Component comp = null;
	boolean noDraw = false;
	
	public static final int moveHandle = -1;
	public static final int noHit      = 0;
	public static final int nwHandle   = 1;
	public static final int wHandle    = 2;
	public static final int swHandle   = 3;
	public static final int neHandle   = 4;
	public static final int eHandle    = 5;
	public static final int seHandle   = 6;
	public static final int nHandle    = 7;
	public static final int sHandle    = 8;
	
	
	public JHandle(Component c) 
	{
		comp = c;
		Rectangle b = c.getBounds();
		x = b.x-5;// - c.getParent().insets().left;
		y = b.y-5;// - c.getParent().insets().top;
		width = b.width+10;
		height = b.height+10;
		//System.out.println("insets; "+c.getParent().insets()+" bounds:
"+c.bounds());
		//System.out.println("x:"+x+" y:"+y+" w:"+width+" h:"+height);
	}
	
	
	public int hitHandle(int dx, int dy) 
	{
		if (comp.getBounds().contains(dx, dy))
			return JHandle.noHit;

		// now translate the point to the handle to make computation easier
		dx = dx - x;
		dy = dy - y;
        if ((dx < 0) || (dy < 0) || (dx > width) || (dy > height))
            return JHandle.noHit;
		if (dx < 10) {
			if (dy < 10)
				return JHandle.nwHandle;
			if (dy > height - 9)
				return JHandle.swHandle;
			if ((dy > (height/2)-3) && (dy < (height/2)+3))
				return JHandle.wHandle;
			return JHandle.moveHandle;
		}
		if (dx > width - 10) {
			if (dy < 10)
				return JHandle.neHandle;
			if (dy > height - 9)
				return JHandle.seHandle;
			if ((dy > (height/2)-3) && (dy < (height/2)+3))
				return JHandle.eHandle;
			return JHandle.moveHandle;
		}
		if ((dx > (width/2)-3) && (dx < (width/2)+3))
			if (dy <= 5)
			return JHandle.nHandle;
		else
			return JHandle.sHandle;
		return JHandle.moveHandle;
	}
	

	public void paint(Graphics g) 
	{
		// Move handles
		if (noDraw) return;
		Color back = comp.getParent().getBackground();
		
        g.setColor(back);
        g.fill3DRect(x,y,width, 5, false);
        g.fill3DRect(x,y,5, height, false);
        g.fill3DRect(x+width-5, y, 5, height, false);
        g.fill3DRect(x,y+height-5, width, 5, false);
		
		// Resize handles upper left
		g.setColor(back);
		g.fillRect(x,y,9,4);
		g.fillRect(x,y,4,9);
		g.setColor(back.brighter());
		g.drawLine(x,y,x+9,y);
		g.drawLine(x,y,x,y+9);
		g.setColor(back.darker());
		g.drawLine(x+1,y+9,x+4,y+9);
		g.drawLine(x+4,y+4,x+4,y+9);
		g.drawLine(x+4,y+4,x+9,y+4);
		g.drawLine(x+9,y+1,x+9,y+4);
		
		// Resize handles upper right
		g.setColor(back);
		g.fillRect(x+width-10,y,9,4);
		g.fillRect(x+width-5,y,4,9);
		g.setColor(back.brighter());
		g.drawLine(x+width-10,y,x+width-1,y);
		g.drawLine(x+width-10,y,x+width-10,y+4);
		g.drawLine(x+width-5,y+5,x+width-5,y+9);
		g.setColor(back.darker());
		g.drawLine(x+width-9,y+4,x+width-5,y+4);
		g.drawLine(x+width-4,y+9,x+width-1,y+9);
		g.drawLine(x+width-1,y+1,x+width-1,y+9);
		
		// Resize handles lower left
		g.setColor(back);
		g.fillRect(x,y+height-10,4,9);
		g.fillRect(x,y+height-5,9,4);
		g.setColor(back.brighter());
		g.drawLine(x,y+height-10,x+4,y+height-10);
		g.drawLine(x,y+height-10,x,y+height-1);
		g.drawLine(x+4,y+height-5,x+9,y+height-5);
		g.setColor(back.darker());
		g.drawLine(x+4,y+height-9,x+4,y+height-5);
		g.drawLine(x+1,y+height-1,x+9,y+height-1);
		g.drawLine(x+9,y+height-4,x+9,y+height-1);
		
		// Resize handles lower right
		g.setColor(back);
		g.fillRect(x+width-10,y+height-5,9,4);
		g.fillRect(x+width-5,y+height-10,4,9);
		g.setColor(back.brighter());
		g.drawLine(x+width-5,y+height-10,x+width-1,y+height-10);
		g.drawLine(x+width-5,y+height-10,x+width-5,y+height-5);
		g.drawLine(x+width-10,y+height-5,x+width-5,y+height-5);
		g.drawLine(x+width-10,y+height-5,x+width-10,y+height-1);
		g.setColor(back.darker());
		g.drawLine(x+width-9,y+height-1,x+width-1,y+height-1);
		g.drawLine(x+width-1,y+height-9,x+width-1,y+height-1);
		
		g.setColor(back);
		g.fill3DRect(x+(width/2)-3, y, 7, 5, true);
		g.fill3DRect(x+(width/2)-3, y+height-5, 7, 5, true);
		g.fill3DRect(x, y+(height/2)-3, 5, 7, true);
		g.fill3DRect(x+width-5, y+(height/2)-3, 5, 7, true);
	}
	
	public boolean handleCursor(int dx, int dy, Frame frame) 
	{
		return handleCursor(hitHandle(dx, dy), frame);
	}
	
	public boolean handleCursor(int hitType, Frame frame) 
	{
		Cursor c = null;
		switch(hitType) 
		{
		case JHandle.moveHandle:
			c = new Cursor(Cursor.MOVE_CURSOR);
			break;
		case JHandle.nwHandle:
			c = new Cursor(Cursor.NW_RESIZE_CURSOR);
			break;
		case JHandle.wHandle:
			c = new Cursor(Cursor.W_RESIZE_CURSOR);
			break;
		case JHandle.swHandle:
			c = new Cursor(Cursor.SW_RESIZE_CURSOR);
			break;
		case JHandle.neHandle:
			c = new Cursor(Cursor.NE_RESIZE_CURSOR);
			break;
		case JHandle.eHandle:
			c = new Cursor(Cursor.E_RESIZE_CURSOR);
			break;
		case JHandle.seHandle:
			c = new Cursor(Cursor.SE_RESIZE_CURSOR);
			break;
		case JHandle.nHandle:
			c = new Cursor(Cursor.N_RESIZE_CURSOR);
			break;
		case JHandle.sHandle:
			c = new Cursor(Cursor.S_RESIZE_CURSOR);
			break;
		case JHandle.noHit:
		default:
			return false;
		}
		frame.setCursor(c);
		return true;
	}

	public Cursor handleCursor(int hitType) 
	{
		int cursorType = Cursor.DEFAULT_CURSOR;
		switch(hitType) 
		{
		case JHandle.moveHandle:
			cursorType = Cursor.MOVE_CURSOR;
			break;
		case JHandle.nwHandle:
			cursorType = Cursor.NW_RESIZE_CURSOR;
			break;
		case JHandle.wHandle:
			cursorType = Cursor.W_RESIZE_CURSOR;
			break;
		case JHandle.swHandle:
			cursorType = Cursor.SW_RESIZE_CURSOR;
			break;
		case JHandle.neHandle:
			cursorType = Cursor.NE_RESIZE_CURSOR;
			break;
		case JHandle.eHandle:
			cursorType = Cursor.E_RESIZE_CURSOR;
			break;
		case JHandle.seHandle:
			cursorType = Cursor.SE_RESIZE_CURSOR;
			break;
		case JHandle.nHandle:
			cursorType = Cursor.N_RESIZE_CURSOR;
			break;
		case JHandle.sHandle:
			cursorType = Cursor.S_RESIZE_CURSOR;
			break;
		case JHandle.noHit:
		default:
			cursorType = Cursor.DEFAULT_CURSOR;
			break;
		}
		
		return Cursor.getPredefinedCursor(cursorType);
	}
	
}

Jim Adams
###@###.###
SAS Institute

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: generic FIXED IN: 1.1.5 1.2 INTEGRATED IN: 1.1.5 1.2
14-06-2004

SUGGESTED FIX Made changes to awt_Component.cpp and awt_Toolkit.cpp. Reviewed by Robert Bruce. Also see BugId 4058818, where the changes fixed that bug as well. In awt_Component.cpp, removed WM_MOUSEMOVE simulation in SetCursor, and changed MouseMove function to set m_dragged flag and not eat mouse messages. mike.somlo@eng 1997-10-14
14-10-1997

EVALUATION This is in fact a bug. The problem is the generation of a spurious mouse pressed event when exiting the component in question. Therefore this is *not* a duplicate of 4034656 as suggested in the description. jonathan.locke@Eng 1997-05-01
01-05-1997

PUBLIC COMMENTS Mouse exiting on Win32 can generate spurious mouse press events jonathan.locke@Eng 1997-05-01
01-05-1997

WORK AROUND No reasonable workaround is possible. jonathan.locke@Eng 1997-05-01
01-05-1997