summaryrefslogtreecommitdiff
path: root/src/Fl_Button.cxx
diff options
context:
space:
mode:
authorMatthias Melcher <github@matthiasm.com>2024-01-17 18:54:01 +0100
committerMatthias Melcher <github@matthiasm.com>2024-01-17 18:54:07 +0100
commita038e557835a0b1e8700c53f267043856f22055f (patch)
tree96b88eab46cdefb9911272268f92c897d7cafa64 /src/Fl_Button.cxx
parent0dfa37f4c07beae4fb5a2118b1b67286d37a0c72 (diff)
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.
Diffstat (limited to 'src/Fl_Button.cxx')
-rw-r--r--src/Fl_Button.cxx257
1 files changed, 108 insertions, 149 deletions
diff --git a/src/Fl_Button.cxx b/src/Fl_Button.cxx
index a70fb672c..b8fe5a6a1 100644
--- a/src/Fl_Button.cxx
+++ b/src/Fl_Button.cxx
@@ -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 {
- value(oldval);
+ 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 (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();
+ if (type() == FL_RADIO_BUTTON) setonly();
+ else if (type() == FL_TOGGLE_BUTTON) oldval = value_;
+ else {
+ value(oldval);
+ set_changed();
+ if (when() & FL_WHEN_CHANGED) {
+ Fl_Widget_Tracker wp(this);
+ do_callback(FL_REASON_CHANGED);
+ if (wp.deleted()) return 1;
+ }
+ }
+ if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_RELEASED);
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();
+ 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 {
- clear_changed();
+ simulate_key_action();
}
- } 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 (wp.deleted()) return 1;
+ if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_RELEASED);
+ return 1;
}
- return 1;
- }
- /* FALLTHROUGH */
- default:
- return 0;
+ /* 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 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()).
-
- 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.
+ The constructor creates the button using the given position, size, and label.
- 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.
+ The default box type is box(FL_UP_BOX).
- 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()`.
+ 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()).
- 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`.
+ Derived classes may handle this differently.
- 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.
+ 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.
- \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)