Somehow this message didn't show up in fltk.bugs, so I'm repeating it here.

I would like to close this STR (1894) soon, therefore I ask you to test it with your own _application_ code before I commit it, because it is very "deep inside" the internals of FLTK: Fl_Widget's destructor and Fl_Group::clear() and remove().

You can read the full story via the link below (STR 1894).

If someone would like to test it with FLTK 1.1 then I can also create a patch/diff for 1.1 - just drop a note here.

Thanks in advance for your time and feedback :-)

Albrecht

P.S.: Happy new year to all !


-------- Original Message --------

DO NOT REPLY TO THIS MESSAGE.  INSTEAD, POST ANY RESPONSES TO THE LINK BELOW.

[STR New]

Link: http://www.fltk.org/str.php?L1894
Version: 1.3-current
Fix Version: 1.3.0


Attached is my proposed patch (del_widget-r_6608.patch).

The changes are:

- Fl_Widget's destructor removes the widget from its parent group

- Fl_Group::clear() removes widgets one by one [1] from the group and
deletes them

- Fl_Value_Input.H: added destructor

- Fl_Value_Input.cxx: destructor "repairs" the kludge done in the
constructor [2].

A similar patch works in my private copy in production code for a long
time now (several months). The earlier mentioned problem(s) with static
widgets turned out to be the Fl_Value_Input kludge which can't easily be
removed without bigger code changes.

However, it is still useful to remove _static_ widgets from groups
_before_ deleting the group itself, because otherwise the static widget's
destructor would be called twice (once when deleting the group and once at
program exit, when the system calls destructors of static widgets).

Please test this patch with your application code, I'm fairly sure that
there are no problems with FLTK itself and with my own code, although my
code heavily creates and deletes widgets.

I suggest to commit this to svn for FLTK 1.3 ASAP, hopefully after some
positive feedback :-) , so that we can have more tests when it is in svn.

------
Notes:

[1] This enables a widget to deletes other widgets in its destructor and
thus also to remove them from their parent groups, even if this would be
the same group (this failed before and was one reason for multiple
destructor calls).

[2] This kludge is currently necessary for correct event handling (and has
always been there), but make the destructor fail, if it tries to remove a
widget from its parent, because this parent widget is _not_ a Fl_Group.


Link: http://www.fltk.org/str.php?L1894
Version: 1.3-current
Fix Version: 1.3.0


Index: src/Fl_Value_Input.cxx
===================================================================
--- src/Fl_Value_Input.cxx      (revision 6608)
+++ src/Fl_Value_Input.cxx      (working copy)
@@ -136,6 +136,12 @@
   set_flag(SHORTCUT_LABEL);
 }
 
+Fl_Value_Input::~Fl_Value_Input() {
+
+  if (input.parent() == (Fl_Group *)this)
+    input.parent(0);   // *revert* ctor kludge!
+}
+
 //
 // End of "$Id$".
 //
Index: src/Fl_Group.cxx
===================================================================
--- src/Fl_Group.cxx    (revision 6608)
+++ src/Fl_Group.cxx    (working copy)
@@ -383,21 +383,23 @@
   affects all child widgets and deletes them from memory.
 */
 void Fl_Group::clear() {
-  Fl_Widget*const* old_array = array();
-  int old_children = children();
-  // clear everything now, in case fl_fix_focus recursively calls us:
-  children_ = 0;
-  //array_ = 0; //dont do this, it will clobber old_array if only one child
   savedfocus_ = 0;
   resizable_ = this;
   init_sizes();
   // okay, now it is safe to destroy the children:
-  Fl_Widget*const* a = old_array;
-  for (int i=old_children; i--;) {
-    Fl_Widget* o = *a++;
-    if (o->parent() == this) delete o;
+  while (children_) {
+    Fl_Widget* o = child(0);   // *first* child widget
+    if (o->parent() == this) { // should always be true
+      remove(o);               // remove child widget first
+      delete o;                        // then delete it
+    } else {                   // this should never happen !
+#ifdef DEBUG_CLEAR
+      printf ("Fl_Group::clear() widget:%p, parent: %p != this (%p)\n",
+             o, o->parent(), this); fflush(stdout);
+#endif // DEBUG_CLEAR
+      remove(o);               // remove it
+    }
   }
-  if (old_children > 1) free((void*)old_array);
 }
 
 /**
@@ -466,7 +468,18 @@
   int i = find(o);
   if (i >= children_) return;
   if (&o == savedfocus_) savedfocus_ = 0;
-  o.parent_ = 0;
+  if (o.parent_ == this) {     // this should always be true
+    o.parent_ = 0;
+  } 
+#ifdef DEBUG_REMOVE  
+  else {                       // this should never happen !
+    printf ("Fl_Group::remove(): widget %p, parent_ (%p) != this (%p)\n",
+      &o, o.parent_, this);
+  }
+#endif // DEBUG_REMOVE
+
+  // remove the widget from the group
+
   children_--;
   if (children_ == 1) { // go from 2 to 1 child
     Fl_Widget *t = array_[!i];
Index: src/Fl_Widget.cxx
===================================================================
--- src/Fl_Widget.cxx   (revision 6608)
+++ src/Fl_Widget.cxx   (working copy)
@@ -135,14 +135,19 @@
 
 /**
    Destroys the widget, taking care of throwing focus before if any.
-   Destruction does not remove from any parent group!  And groups when
-   destroyed destroy all their children.  This is convenient and fast.
-   However, it is only legal to destroy a "root" such as an Fl_Window,
-   and automatic destructors may be called.
+   Destruction removes the widget from any parent group! And groups when
+   destroyed destroy all their children. This is convenient and fast.
 */
 Fl_Widget::~Fl_Widget() {
   Fl::clear_widget_pointer(this);
   if (flags() & COPIED_LABEL) free((void *)(label_.value));
+  // remove from parent group
+  if (parent_) parent_->remove(this);
+#ifdef DEBUG_DELETE
+  if (parent_) { // this should never happen
+    printf("*** Fl_Widget: parent_->remove(this) failed 
[%p,%p]\n",parent_,this);
+  }
+#endif // DEBUG_DELETE
   parent_ = 0; // Don't throw focus to a parent widget.
   fl_throw_focus(this);
 }
Index: FL/Fl_Value_Input.H
===================================================================
--- FL/Fl_Value_Input.H (revision 6608)
+++ FL/Fl_Value_Input.H (working copy)
@@ -76,6 +76,7 @@
   void draw();
   void resize(int,int,int,int);
   Fl_Value_Input(int x,int y,int w,int h,const char *l=0);
+  ~Fl_Value_Input();
 
   /** See void Fl_Value_Input::soft(char s) */
   void soft(char s) {soft_ = s;}

_______________________________________________
fltk-dev mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-dev

Reply via email to