mirror of https://github.com/fltk/fltk
Restore original Fl_Button event behavior(#877)
Previous commits introduced too many changes to Fl_Button callbacks, creating problems in user apps. This is the base for a second much more specific fix to event flags.
This commit is contained in:
parent
0dfa37f4c0
commit
a038e55783
|
@ -32,10 +32,10 @@ Fl_Widget_Tracker *Fl_Button::key_release_tracker = 0;
|
|||
// here. This includes Fl_Radio_Button and Fl_Toggle_Button
|
||||
|
||||
/**
|
||||
Sets the current value of the button.
|
||||
A non-zero value sets the button to 1 (ON), and zero sets it to 0 (OFF).
|
||||
\param[in] v button value.
|
||||
\see set(), clear()
|
||||
Sets the current value of the button.
|
||||
A non-zero value sets the button to 1 (ON), and zero sets it to 0 (OFF).
|
||||
\param[in] v button value.
|
||||
\see set(), clear()
|
||||
*/
|
||||
int Fl_Button::value(int v) {
|
||||
v = v ? 1 : 0;
|
||||
|
@ -52,8 +52,8 @@ int Fl_Button::value(int v) {
|
|||
}
|
||||
|
||||
/**
|
||||
Turns on this button and turns off all other radio buttons in the group
|
||||
(calling \c value(1) or \c set() does not do this).
|
||||
Turns on this button and turns off all other radio buttons in the group
|
||||
(calling \c value(1) or \c set() does not do this).
|
||||
*/
|
||||
void Fl_Button::setonly() { // set this radio button on, turn others off
|
||||
value(1);
|
||||
|
@ -102,112 +102,93 @@ void Fl_Button::draw() {
|
|||
}
|
||||
|
||||
int Fl_Button::handle(int event) {
|
||||
static bool s_key_repeat = false;
|
||||
int newval;
|
||||
switch (event) {
|
||||
case FL_ENTER: /* FALLTHROUGH */
|
||||
case FL_LEAVE:
|
||||
// if ((value_?selection_color():color())==FL_GRAY) redraw();
|
||||
return 1;
|
||||
case FL_PUSH:
|
||||
if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this);
|
||||
/* FALLTHROUGH */
|
||||
case FL_DRAG:
|
||||
if (Fl::event_inside(this)) {
|
||||
if (type() == FL_RADIO_BUTTON) newval = 1;
|
||||
else newval = !oldval;
|
||||
} else {
|
||||
clear_changed();
|
||||
newval = oldval;
|
||||
}
|
||||
if (newval != value_) {
|
||||
value_ = newval;
|
||||
set_changed();
|
||||
redraw();
|
||||
if ((type() == 0) && (when() & FL_WHEN_CHANGED)) do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (value_ == oldval) {
|
||||
clear_changed();
|
||||
} else {
|
||||
if (type() == FL_RADIO_BUTTON) {
|
||||
setonly();
|
||||
} else if (type() == FL_TOGGLE_BUTTON) {
|
||||
oldval = value_;
|
||||
case FL_ENTER: /* FALLTHROUGH */
|
||||
case FL_LEAVE:
|
||||
// if ((value_?selection_color():color())==FL_GRAY) redraw();
|
||||
return 1;
|
||||
case FL_PUSH:
|
||||
if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this);
|
||||
/* FALLTHROUGH */
|
||||
case FL_DRAG:
|
||||
if (Fl::event_inside(this)) {
|
||||
if (type() == FL_RADIO_BUTTON) newval = 1;
|
||||
else newval = !oldval;
|
||||
} else {
|
||||
clear_changed();
|
||||
newval = oldval;
|
||||
}
|
||||
if (newval != value_) {
|
||||
value_ = newval;
|
||||
set_changed();
|
||||
redraw();
|
||||
if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (value_ == oldval) {
|
||||
if (when() & FL_WHEN_NOT_CHANGED) do_callback(FL_REASON_SELECTED);
|
||||
return 1;
|
||||
}
|
||||
set_changed();
|
||||
if (type() == FL_RADIO_BUTTON) setonly();
|
||||
else if (type() == FL_TOGGLE_BUTTON) oldval = value_;
|
||||
else {
|
||||
value(oldval);
|
||||
}
|
||||
set_changed();
|
||||
}
|
||||
if (changed() && (when() & FL_WHEN_CHANGED))
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
else if (!changed() && (when() & FL_WHEN_NOT_CHANGED))
|
||||
do_callback(FL_REASON_SELECTED);
|
||||
else if (when() & FL_WHEN_RELEASE)
|
||||
do_callback(FL_REASON_RELEASED);
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if (!(shortcut() ?
|
||||
Fl::test_shortcut(shortcut()) : test_shortcut())) return 0;
|
||||
if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this);
|
||||
goto triggered_by_keyboard;
|
||||
case FL_FOCUS :
|
||||
case FL_UNFOCUS :
|
||||
if (Fl::visible_focus()) {
|
||||
if (box() == FL_NO_BOX) {
|
||||
// Widgets with the FL_NO_BOX boxtype need a parent to
|
||||
// redraw, since it is responsible for redrawing the
|
||||
// background...
|
||||
int X = x() > 0 ? x() - 1 : 0;
|
||||
int Y = y() > 0 ? y() - 1 : 0;
|
||||
if (window()) window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2);
|
||||
} else redraw();
|
||||
return 1;
|
||||
} else return 0;
|
||||
/* NOTREACHED */
|
||||
case FL_KEYUP:
|
||||
s_key_repeat = false;
|
||||
return 0;
|
||||
case FL_KEYBOARD :
|
||||
if (Fl::focus() == this && Fl::event_key() == ' ' &&
|
||||
!(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) {
|
||||
triggered_by_keyboard:
|
||||
if (s_key_repeat) return 1;
|
||||
Fl_Widget_Tracker wp(this);
|
||||
if (type() == FL_RADIO_BUTTON) {
|
||||
if (!value_) {
|
||||
setonly();
|
||||
set_changed();
|
||||
} else {
|
||||
clear_changed();
|
||||
set_changed();
|
||||
if (when() & FL_WHEN_CHANGED) {
|
||||
Fl_Widget_Tracker wp(this);
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
if (wp.deleted()) return 1;
|
||||
}
|
||||
} else if (type() == FL_TOGGLE_BUTTON) {
|
||||
value(!value());
|
||||
set_changed();
|
||||
} else {
|
||||
set_changed();
|
||||
}
|
||||
|
||||
if (changed() && (when() & FL_WHEN_CHANGED))
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
else if (!changed() && (when() & FL_WHEN_NOT_CHANGED))
|
||||
do_callback(FL_REASON_SELECTED);
|
||||
else if (when() & FL_WHEN_RELEASE)
|
||||
do_callback(FL_REASON_RELEASED);
|
||||
s_key_repeat = true;
|
||||
if (wp.deleted()) return 1; // leave if the widget was deleted in the callback
|
||||
|
||||
if ((type() != FL_RADIO_BUTTON) && (type() != FL_TOGGLE_BUTTON)) {
|
||||
simulate_key_action(); // for visual feedback only
|
||||
}
|
||||
if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_RELEASED);
|
||||
return 1;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return 0;
|
||||
case FL_SHORTCUT:
|
||||
if (!(shortcut() ?
|
||||
Fl::test_shortcut(shortcut()) : test_shortcut())) return 0;
|
||||
if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this);
|
||||
goto triggered_by_keyboard;
|
||||
case FL_FOCUS :
|
||||
case FL_UNFOCUS :
|
||||
if (Fl::visible_focus()) {
|
||||
if (box() == FL_NO_BOX) {
|
||||
// Widgets with the FL_NO_BOX boxtype need a parent to
|
||||
// redraw, since it is responsible for redrawing the
|
||||
// background...
|
||||
int X = x() > 0 ? x() - 1 : 0;
|
||||
int Y = y() > 0 ? y() - 1 : 0;
|
||||
if (window()) window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2);
|
||||
} else redraw();
|
||||
return 1;
|
||||
} else return 0;
|
||||
/* NOTREACHED */
|
||||
case FL_KEYBOARD :
|
||||
if (Fl::focus() == this && Fl::event_key() == ' ' &&
|
||||
!(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) {
|
||||
set_changed();
|
||||
triggered_by_keyboard:
|
||||
Fl_Widget_Tracker wp(this);
|
||||
if (type() == FL_RADIO_BUTTON) {
|
||||
if (!value_) {
|
||||
setonly();
|
||||
if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
} else if (type() == FL_TOGGLE_BUTTON) {
|
||||
value(!value());
|
||||
if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
} else {
|
||||
simulate_key_action();
|
||||
}
|
||||
if (wp.deleted()) return 1;
|
||||
if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_RELEASED);
|
||||
return 1;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Fl_Button::simulate_key_action()
|
||||
|
@ -238,65 +219,43 @@ void Fl_Button::key_release_timeout(void *d)
|
|||
}
|
||||
|
||||
/**
|
||||
The constructor creates the button using the given position, size, and label.
|
||||
The constructor creates the button using the given position, size, and label.
|
||||
|
||||
The default box type is box(FL_UP_BOX).
|
||||
The default box type is box(FL_UP_BOX).
|
||||
|
||||
You can control how the button is drawn when ON by setting down_box().
|
||||
The default is FL_NO_BOX (0) which will select an appropriate box type
|
||||
using the normal (OFF) box type by using fl_down(box()).
|
||||
You can control how the button is drawn when ON by setting down_box().
|
||||
The default is FL_NO_BOX (0) which will select an appropriate box type
|
||||
using the normal (OFF) box type by using fl_down(box()).
|
||||
|
||||
Derived classes may handle this differently.
|
||||
Derived classes may handle this differently.
|
||||
|
||||
A button may request callbacks by setting bits in the \p when() bitfield.
|
||||
Only one callback is called for any one event. If multiple bits are set,
|
||||
only the first callback in the list below will be called.
|
||||
A button may reequest callbacks with \p whne() \p FL_WHEN_CHANGED,
|
||||
\p FL_WHEN_NOT_CHANGED, and \p FL_WHEN_RELEASE, triggering the callback
|
||||
reasons \p FL_REASON_CHANGED, \p FL_REASON_SELECTED,
|
||||
and \p FL_REASON_DESELECTED.
|
||||
|
||||
If the `FL_WHEN_CHANGED` bit is set, the callback is called when the mouse
|
||||
button is released, the shortcut key was pressed, or the button has focus
|
||||
and the space bar was pressed, and the value of the button changed. A regular
|
||||
button (not a radio or toggle button) callback is also triggered by key
|
||||
repeat events. The callback reason is set to `FL_REASON_CHANGED`.
|
||||
`Fl_Button::changed()` is !=0, and `Fl_Button::value()` is set to the new
|
||||
value for radio and check buttons.
|
||||
|
||||
If `FL_WHEN_NOT_CHANGED` is set, the callback is called for the same events
|
||||
as above, but only if the value did *not* change. The callback reason is
|
||||
`FL_REASON_SELECTED`. This bit is usually combined with other bits in `when()`.
|
||||
|
||||
The default setting is `FL_WHEN_RELEASE`. If this flag is set, the callback is
|
||||
called when the mouse button or the shortcut key is released. Toggle and radio
|
||||
button callbacks are called, even if the value did not change, however the
|
||||
`Fl_Button::changed()` flag is set accordingly. The callback reason is given
|
||||
as `FL_REASON_RELEASED`.
|
||||
|
||||
When a radio button changes other radio buttons in the same group, only the
|
||||
user activated button will trigger its callback according to the flags above.
|
||||
The other widgets in the group will change their value, but not call their
|
||||
corresponding callbacks.
|
||||
|
||||
\param[in] X, Y, W, H position and size of the widget
|
||||
\param[in] L widget label, default is no label
|
||||
\param[in] X, Y, W, H position and size of the widget
|
||||
\param[in] L widget label, default is no label
|
||||
*/
|
||||
Fl_Button::Fl_Button(int X, int Y, int W, int H, const char *L)
|
||||
: Fl_Widget(X,Y,W,H,L),
|
||||
shortcut_(0),
|
||||
value_(0),
|
||||
oldval(0),
|
||||
down_box_(FL_NO_BOX),
|
||||
compact_(0)
|
||||
shortcut_(0),
|
||||
value_(0),
|
||||
oldval(0),
|
||||
down_box_(FL_NO_BOX),
|
||||
compact_(0)
|
||||
{
|
||||
box(FL_UP_BOX);
|
||||
set_flag(SHORTCUT_LABEL);
|
||||
}
|
||||
|
||||
/**
|
||||
The constructor creates the button using the given position, size, and label.
|
||||
The constructor creates the button using the given position, size, and label.
|
||||
|
||||
The Button type() is set to FL_RADIO_BUTTON.
|
||||
The Button type() is set to FL_RADIO_BUTTON.
|
||||
|
||||
\param[in] X, Y, W, H position and size of the widget
|
||||
\param[in] L widget label, default is no label
|
||||
\param[in] X, Y, W, H position and size of the widget
|
||||
\param[in] L widget label, default is no label
|
||||
*/
|
||||
Fl_Radio_Button::Fl_Radio_Button(int X,int Y,int W,int H,const char *L)
|
||||
: Fl_Button(X, Y, W, H, L) {
|
||||
|
@ -304,12 +263,12 @@ Fl_Radio_Button::Fl_Radio_Button(int X,int Y,int W,int H,const char *L)
|
|||
}
|
||||
|
||||
/**
|
||||
The constructor creates the button using the given position, size, and label.
|
||||
The constructor creates the button using the given position, size, and label.
|
||||
|
||||
The Button type() is set to FL_TOGGLE_BUTTON.
|
||||
The Button type() is set to FL_TOGGLE_BUTTON.
|
||||
|
||||
\param[in] X, Y, W, H position and size of the widget
|
||||
\param[in] L widget label, default is no label
|
||||
\param[in] X, Y, W, H position and size of the widget
|
||||
\param[in] L widget label, default is no label
|
||||
*/
|
||||
Fl_Toggle_Button::Fl_Toggle_Button(int X,int Y,int W,int H,const char *L)
|
||||
: Fl_Button(X,Y,W,H,L)
|
||||
|
|
Loading…
Reference in New Issue