STR #1162: Fl_Menu_Button::popup was trying to access a previously deleted widget (itself). The delayed deleting mechanism in 'Fl::delete_widget' did not work in this case because the main loop is called before the callback returns. The fix implements a type of automatic pointer that will be cleared to NULL should the widget get deleted. This may not be a 'nice' solution, but it does fix the problem reliably. We could actually use this for all widget pointers and remove the delayed delete mechanism alltogether
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@5037 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
cbbec03b5e
commit
ad0fc9ca23
2
CHANGES
2
CHANGES
@ -1,5 +1,7 @@
|
|||||||
CHANGES IN FLTK 1.1.8
|
CHANGES IN FLTK 1.1.8
|
||||||
|
|
||||||
|
- Fixed usage of deleted object after menu pulldown
|
||||||
|
(STR #1162)
|
||||||
- Calling fl_font(0, 0) under Xft would access a NULL
|
- Calling fl_font(0, 0) under Xft would access a NULL
|
||||||
pointer (STR #1205)
|
pointer (STR #1205)
|
||||||
- Setting a new value in Fl_Input_ wil now actually move
|
- Setting a new value in Fl_Input_ wil now actually move
|
||||||
|
3
FL/Fl.H
3
FL/Fl.H
@ -271,6 +271,9 @@ public:
|
|||||||
// Widget deletion:
|
// Widget deletion:
|
||||||
static void delete_widget(Fl_Widget *w);
|
static void delete_widget(Fl_Widget *w);
|
||||||
static void do_widget_deletion();
|
static void do_widget_deletion();
|
||||||
|
static void watch_widget_pointer(Fl_Widget *&w);
|
||||||
|
static void release_widget_pointer(Fl_Widget *&w);
|
||||||
|
static void clear_widget_pointer(Fl_Widget const *w);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !Fl_H
|
#endif // !Fl_H
|
||||||
|
47
src/Fl.cxx
47
src/Fl.cxx
@ -1207,6 +1207,53 @@ Fl::do_widget_deletion() {
|
|||||||
num_dwidgets = 0;
|
num_dwidgets = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Fl_Widget ***widget_watch = 0;
|
||||||
|
static int num_widget_watch = 0;
|
||||||
|
static int max_widget_watch = 0;
|
||||||
|
|
||||||
|
void Fl::watch_widget_pointer(Fl_Widget *&w)
|
||||||
|
{
|
||||||
|
Fl_Widget **wp = &w;
|
||||||
|
int i;
|
||||||
|
for (i=0; i<num_widget_watch; ++i) {
|
||||||
|
if (widget_watch[i]==wp) return;
|
||||||
|
}
|
||||||
|
for (i=0; i<num_widget_watch; ++i) {
|
||||||
|
if (widget_watch[i]==0L) {
|
||||||
|
widget_watch[i] = wp;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num_widget_watch==max_widget_watch) {
|
||||||
|
max_widget_watch += 8;
|
||||||
|
widget_watch = (Fl_Widget***)realloc(widget_watch, sizeof(Fl_Widget**)*max_widget_watch);
|
||||||
|
}
|
||||||
|
widget_watch[num_widget_watch++] = wp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl::release_widget_pointer(Fl_Widget *&w)
|
||||||
|
{
|
||||||
|
Fl_Widget **wp = &w;
|
||||||
|
int i;
|
||||||
|
for (i=0; i<num_widget_watch; ++i) {
|
||||||
|
if (widget_watch[i]==wp) {
|
||||||
|
widget_watch[i] = 0L;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fl::clear_widget_pointer(Fl_Widget const *w)
|
||||||
|
{
|
||||||
|
if (w==0L) return;
|
||||||
|
int i;
|
||||||
|
for (i=0; i<num_widget_watch; ++i) {
|
||||||
|
if (widget_watch[i] && *widget_watch[i]==w) {
|
||||||
|
*widget_watch[i] = 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// End of "$Id$".
|
// End of "$Id$".
|
||||||
|
@ -51,6 +51,8 @@ const Fl_Menu_Item* Fl_Menu_Button::popup() {
|
|||||||
const Fl_Menu_Item* m;
|
const Fl_Menu_Item* m;
|
||||||
pressed_menu_button_ = this;
|
pressed_menu_button_ = this;
|
||||||
redraw();
|
redraw();
|
||||||
|
Fl_Widget *mb = this;
|
||||||
|
Fl::watch_widget_pointer(mb);
|
||||||
if (!box() || type()) {
|
if (!box() || type()) {
|
||||||
m = menu()->popup(Fl::event_x(), Fl::event_y(), label(), mvalue(), this);
|
m = menu()->popup(Fl::event_x(), Fl::event_y(), label(), mvalue(), this);
|
||||||
} else {
|
} else {
|
||||||
@ -58,7 +60,8 @@ const Fl_Menu_Item* Fl_Menu_Button::popup() {
|
|||||||
}
|
}
|
||||||
picked(m);
|
picked(m);
|
||||||
pressed_menu_button_ = 0;
|
pressed_menu_button_ = 0;
|
||||||
redraw();
|
if (mb) mb->redraw();
|
||||||
|
Fl::release_widget_pointer(mb);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +133,7 @@ extern void fl_throw_focus(Fl_Widget*); // in Fl_x.cxx
|
|||||||
// However, it is only legal to destroy a "root" such as an Fl_Window,
|
// However, it is only legal to destroy a "root" such as an Fl_Window,
|
||||||
// and automatic destructors may be called.
|
// and automatic destructors may be called.
|
||||||
Fl_Widget::~Fl_Widget() {
|
Fl_Widget::~Fl_Widget() {
|
||||||
|
Fl::clear_widget_pointer(this);
|
||||||
if (flags() & COPIED_LABEL) free((void *)(label_.value));
|
if (flags() & COPIED_LABEL) free((void *)(label_.value));
|
||||||
parent_ = 0; // Don't throw focus to a parent widget.
|
parent_ = 0; // Don't throw focus to a parent widget.
|
||||||
fl_throw_focus(this);
|
fl_throw_focus(this);
|
||||||
|
Loading…
Reference in New Issue
Block a user