Tk Library Source Code

View Ticket
Login
Ticket UUID: 472718
Title: ScrollWindow update idletasks
Type: Bug Version: None
Submitter: nobody Created on: 2001-10-19 10:45:37
Subsystem: bwidget Assigned To: hobbs
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2003-02-26 05:13:37
Resolution: Fixed Closed By: hobbs
    Closed on: 2003-02-25 22:13:36
Description:
I have noticed that in some rare cases the "update 
idletask" command added into 
ScrolledWindow::_set_hscroll and 
ScrolledWindow::_set_vscroll procs enter into a 
infinite loop.
I think loop borns when _set_hscroll or _set_vscroll 
changes the displayed portions of the contained widget
(setwidget), thus "update idletask" reach a 
<configure> binding on the contained widget wich call 
again _set_hscroll or _set_vscroll.
Sorry I can't provide a source example, but I'm using 
Bwidget embedded into a commercial app.
User Comments: hobbs added on 2003-02-26 05:13:37:

File Added - 43462: scrollw.patch

hobbs added on 2003-02-26 05:13:36:
Logged In: YES 
user_id=72656

Applied paul's patch - it corrects the small window infinite 
loop problem.  Patch attached.  All seems happy!

pkienzle added on 2003-02-25 21:40:06:
Logged In: YES 
user_id=40262

My example still fails (BWidget from CVS 2003-02-25 9:00am,
configure.in says 1.6, pkgIndex says 1.5, wish 8.3.1 or
8.4.0, RH linux). I haven't checked windows yet.

ScrolledWindow .textbox
text .textbox.text -wrap no -height 2 -width 6
.textbox setwidget .textbox.text
pack .textbox -fill both -expand yes
.textbox.text insert 0.0 "Line 1\nLine 2\nLong line 3"

hobbs added on 2003-02-25 17:04:23:

File Added - 43397: scrollw.tcl

Logged In: YES 
user_id=72656

A complete rewrite of ScrolledWindow is attached that 
corrects the problems.  It may have slight behavior 
irregularities as I rewrote it from scratch and there are several 
undoc'ed features of ScrolledWindow, but it does 
behave "correctly", and doesn't suffer from the infinite loop 
problem.

nobody added on 2002-05-29 17:45:01:
Logged In: NO 

The following procs avoid infinite loop but they have the 
limitations to hide 1/10 of the contained widget before 
displaying scrollbars. The loop borns with these calls:

_set_vscroll  { 0 0.934343 }
_set_hscroll  { 0 0.961538 }
_set_vscroll  { 0 1 }
_set_hscroll  { 0 1 }

# -----------------------------------------------------------------------------
#  Command ScrolledWindow::_set_hscroll
# -----------------------------------------------------------------------------
proc ScrolledWindow::_set_hscroll { path vmin vmax } {
    upvar \#0 ScrolledWindow::$path data

    if {$data(realized) && $data(hsb,present)} {
        set grid $path._grid
        if {$data(hsb,auto)} {
            if {$data(hsb,packed) && $vmin == 0 && $vmax == 
1} {
                set data(hsb,packed) 0
                grid configure $grid.f $grid.vframe -row 0 -rowspan 2
            
            # G. Bloisi 29/May/2002, IONTrading
            } elseif {!$data(hsb,packed) && ($vmin != 0 || $vmax < 
0.9)} {
                set data(hsb,packed) 1
                grid configure $grid.f $grid.vframe -row $data
(hsb,north) -rowspan 1
            }
        }
# G. Bloisi 19/Oct/2001, IONTrading
#update idletasks
        $grid.hscroll set $vmin $vmax
    }
}


# -----------------------------------------------------------------------------
#  Command ScrolledWindow::_set_vscroll
# -----------------------------------------------------------------------------
proc ScrolledWindow::_set_vscroll { path vmin vmax } {
    upvar \#0 ScrolledWindow::$path data

    if {$data(realized) && $data(vsb,present)} {
        set grid $path._grid
        if {$data(vsb,auto)} {
            if {$data(vsb,packed) && $vmin == 0 && $vmax == 1} 
{
                set data(vsb,packed) 0
                grid configure $grid.f $grid.hframe -column 0 -
columnspan 2
                
# G. Bloisi 29/May/2002, 
IONTrading            
            } elseif {!$data(vsb,packed) && ($vmin != 0 || $vmax < 
0.9) } {
                set data(vsb,packed) 1
                grid configure $grid.f $grid.hframe -column $data
(vsb,west) -columnspan 1
            }
        }
# G. Bloisi 19/Oct/2001, IONTrading
#update idletasks
        $grid.vscroll set $vmin $vmax
    }
}

proc ScrolledWindow::_setSBSize {sb size args} {
# G. Bloisi 29/May/2002, IONTrading
bind $sb <Configure> {}

    $sb configure -width $size
    eval place $sb $args
}

nobody added on 2002-03-02 12:13:25:
Logged In: NO 

The following code:

package require BWidget
namespace import BWidget::*
ScrolledWindow .textbox
text .textbox.text -wrap no -height 2 -width 6   
.textbox setwidget .textbox.text   
pack .textbox -fill both -expand yes    
.textbox.text insert 0.0 "Line 1\nLine 2 \
\nVery,very,veryllllllllllllllllllllllllllllllllllllllong 
line 3"

which differs from the example offered here earlier just 
by the length of the line 3 (it is just enough to have the 
line out of the text widget) crashes immediately after 
starting. There is no need to do any resizing.

Tested positive on "quality assured" AS Tcl/Tk 8.3.4.1, BW 
1.3.1, Win 2000/XP, also on freeBSD 4.4 , BW 1.3.1, Tcl/Tk 
8.3.4

It don't seems to be specific only to exotic OSes.

Actually, almost any window which uses ScrolledWindow can 
be crashed just by resizing the widget around the point 
where both scrollbars should appear at the same time. It 
makes ScrolledWindow widget unfortunately unusable.

pkienzle added on 2002-01-23 21:38:19:
Logged In: YES 
user_id=40262

Given a text box with some short lines followed by one long
line as in my example,

  (1) make the box tall enough and wide enough to show the
long line plus a vertical scrollbar

  (2) shorten the box until just the top of the longest line
is shown

  (3) narrow the box until a horizontal scrollbar will be
required

The horizontal scrollbar will shorten the box so that the
longest line will no longer be visible, and so the
horizontal scroll bar will not be required, and so the
horizontal scroll bar will not be displayed, and so the
longest line will again be visible, and so a horizontal
scrollbar will be required which will shorten the box, etc.

It fails with:
  BWidgets 1.3.1
  Tcl/Tk 8.3.1
  Redhat 7.1
  Linux 2.4.2
  XFree86 4.0.3
And also with:
  BWidgets 1.3.1
  Tcl/Tk 8.3.4
  IRIX64 6.2
  XFree86 4.0.3

hobbs added on 2002-01-23 06:44:36:
Logged In: YES 
user_id=72656

Unfortunately any test is sensitive to the actual fonts 
used and geometry given.  If a very precise sample with all 
the OS / fonts / exact geometry can be given, a solution 
may be found.  Otherwise I can't repeat it in the current 
code.

pkienzle added on 2002-01-09 23:38:13:
Logged In: YES 
user_id=40262

The following will cause an infinite loop:

  package require BWidget
  namespace import BWidget::*

  ScrolledWindow .textbox
  text .textbox.text -wrap no -height 2 -width 6
  .textbox setwidget .textbox.text
  pack .textbox -fill both -expand yes

  .textbox.text insert 0.0 "Line 1\nLine 2\nLong line 3"

In this case, would it be possible to keep the horizontal
scroll bar if it will be needed by any line of text rather
than just the lines shown in the window?

Attachments: