Avoid spurious asserts when holding arrows in GTK wxSpinButton

The change in the value can be greater than 1 when the arrows are held
pressed, contrary to what the logic of determining the wraparound added
in 086793ceef supposed.

Replace this with a check of whether we switch from the min value
directly to the max one or vice versa, which mostly works and avoids
asserts, even if it can still fail and produces wrong events when the
arrows are held pressed for long enough to increase the delta to the
range of the control, in which case we just can't distinguish between
wraparound and passing from min to max (or vice versa) in a single step,
which means that we have no way to determine the right event to send.
But producing a wrong event is better than asserting, so this still
counts as an improvement.

Closes https://github.com/wxWidgets/wxWidgets/pull/1764

See #17957.

Closes #18695.
This commit is contained in:
Vadim Zeitlin
2020-03-15 18:09:11 +01:00
parent 34ade14c0f
commit 10c51dbf28

View File

@@ -38,19 +38,35 @@ gtk_value_changed(GtkSpinButton* spinbutton, wxSpinButton* win)
return;
}
int inc = pos - oldPos;
// Adjust for wrap arounds
// (Doesn't work for degenerated cases, like [0..1] range.)
// Normally we can determine which way we're going by just comparing the
// old and the new values.
bool up = pos > oldPos;
// However we need to account for the possibility of wrapping around.
if ( win->HasFlag(wxSP_WRAP) )
{
if ( inc > 1 )
inc = -1;
else if ( inc < -1 )
inc = 1;
}
wxASSERT( inc == 1 || inc == -1 );
// We have no way of distinguishing between wraparound and normal
// change when the range is just 1, as pressing either arrow results in
// the same change, so don't even try doing it in this case.
const int spinMin = win->GetMin();
const int spinMax = win->GetMax();
wxSpinEvent event(inc > 0 ? wxEVT_SCROLL_LINEUP : wxEVT_SCROLL_LINEDOWN, win->GetId());
if ( spinMax - spinMin > 1 )
{
if ( up )
{
if ( oldPos == spinMin && pos == spinMax )
up = false;
}
else // down
{
if ( oldPos == spinMax && pos == spinMin )
up = true;
}
}
}
wxSpinEvent event(up ? wxEVT_SCROLL_LINEUP : wxEVT_SCROLL_LINEDOWN, win->GetId());
event.SetPosition(pos);
event.SetEventObject(win);