Okay, so I decided to do a little research into the whole issue of why the “drag threshold” in Vassal is so hair-trigger, causing one to constantly “lose clicks” (have them interpreted as 1-pixel drags) especially when trying to double-click stacks.
One thing I learned is that, a lot more recently than you’d think, there was no way to set java’s drag threshold (for the drag gesture threshold) AT ALL! So then this bug: bugs.java.com/bugdatabase/view_ … id=4415175 got filed and in due course a new system property was born: awt.dnd.drag.threshold
And so with a mere…
System.setProperty(“awt.dnd.drag.threshold”, “<SOME INTEGER HIGHER THAN FREAKING 1 FOR INSTANCE>”)
…this problem could theoretically go away! But then I actually “tried it”, and at first nothing seemed to happen. So I set it to higher and higher values e.g. surely I couldn’t possibly miss it if it were 80. But it still seemed to do nothing!
So I looked on Stack Overflow for any reference, and I found a single article (stackoverflow.com/questions/223 … -detection) where it was referenced in the second answer, with the interesting aspect that several commenters said that they to had tried the exact thing and it hadn’t worked at all. So that’s a little odd.
So then being “a weirdo” I ran the debugger deep into Java system code (see code snippet below) and determined
(a) The system property does actually get set (e.g. to 80 in my example)
(b) The system property does actually get “checked” at the appropriate time when a drag starts.
(c) BUT… the data for the X and Y differential seemed to be complete garbage. Like I’d move it about 1 pixel and I’d get “origin” of 1312,360 and “current” of 578,455. Made no sense. Almost like… the two points were “in two totally different scales”.
(d) So THEN I said, well what if I zoom the map all the way out to 1-to-1 (100%) scale factor.
(e) LO AND BEHOLD! Suddenly my manually set drag threshold of 80 works perfectly – I have to drag something 80 pixels before it turns into a drag cursor, etc! I suddenly realize that when this is “actually working right”, the normal java default of “5” is probably even about right or at least not-totally-sucky, it’s just that it’s getting garbage data and triggering at even ONE pixel, not even checking the default 5.
SOOOOOOOOoooooooo… after more debugging (I’ve included the key code snippet below), I have determined that at ANY scale other than 100% zoom, the threshold part of the gesture recognizer ends up “comparing apples to oranges” and essentially firing on even a 1 pixel move creating the behavior we all know and don’t love.
So my considered question to the other engineers is: is there anywhere in this chain that VASSAL itself is responsible for populating one or more of these MouseEvents that are getting sent in here? Is it possible that WE are sending improperly scaled data down into the bowels of the gesture recognizer, and therefore screwing up its ability to “recognize drag gestures”, as it were? Because if so, it’s possible that this is an “easy” bug to fix. (The other possibility would be that this has somehow been a bug in Java for over 17 years and nobody has figured it out or reported it – I find this a bit implausible of course).
So if anybody has any thoughts, I would love to hear them.
Yes I’m a bit of a fanatic about mouse interface code. Sorry not sorry
Brian
//WMouseDragGestureRecognizer
public void mouseDragged(MouseEvent e) {
if (!events.isEmpty()) { // gesture pending
int dop = mapDragOperationFromModifiers(e);
if (dop == DnDConstants.ACTION_NONE) {
return;
}
MouseEvent trigger = (MouseEvent)events.get(0);
Point origin = trigger.getPoint();
Point current = e.getPoint();
int dx = Math.abs(origin.x - current.x);
int dy = Math.abs(origin.y - current.y);
if (dx > motionThreshold || dy > motionThreshold) {
fireDragGestureRecognized(dop, ((MouseEvent)getTriggerEvent()).getPoint());
} else
appendEvent(e);
}
}