Tk Source Code

View Ticket
Bounty program for improvements to Tcl and certain Tcl packages.
Ticket UUID: 1566949
Title: [text yview] shows strange behaviour
Type: Bug Version: obsolete: 8.5a4
Submitter: mbroeken Created on: 2006-09-28 10:30:12
Subsystem: 18. [text] Assigned To: fvogel
Priority: 6 Severity: Minor
Status: Closed Last Modified: 2016-01-13 18:06:17
Resolution: Fixed Closed By: fvogel
    Closed on: 2016-01-13 18:06:17
[$text yview] returns two fractions. When using the
first fraction in [$text yview moveto $fraction] I
would expect the fractions returned by [$text yview]
after this moveto to be the same as before the moveto.
Most of the time this is the case. 

Using [$text yview] with Tcl 8.5a4 on Windows shows
some strange behaviour. The fractions before and after
a moveto call are the same, except when the contents of
the text widget are deleted and insert in between the
first [$text yview] and [$text yview moveto $fraction],
even if the contents stay the same.

I've added an example script to show this bug. [test]
shows some output without deleting and replacing the
contents and [test true] shows the output with deleting
and replacing the contents. Notice the difference! I
think this bug might be related to #1499165.
User Comments: fvogel added on 2016-01-13 18:06:17:

TIP #438 has been approved by TCT vote and is now merged to trunk (only - backport to 8.5 was refused).

Closing this ticket then.

fvogel added on 2015-12-05 13:20:14:

TIP #438 provides a solution to the issue reported in this ticket.

fvogel added on 2015-10-31 20:33:54:

See also [e51941c1b9].

fvogel added on 2015-10-11 19:04:21:

  .t count -update -ypixels 1.0 end

just before calling:
  .t yview moveto $fraction

fvogel added on 2015-10-10 13:41:49:
Reproduced with current core-8-5-branch and trunk.

Test script:

  package require Tk
  catch {destroy .t .ys}
  scrollbar .ys
  text .t -yscrollcommand [list .ys set]
    .t debug on
  .ys configure -command [list .t yview]
  grid .t -row 0 -column 0 -sticky nesw
  grid .ys -row 0 -column 1 -sticky ns
  set content {}
  for {set i 1} {$i < 10} {incr i} {
      append content [string repeat "$i " 150]
      append content \n
  set content [string repeat $content 20]
  .t insert 1.0 $content
  .t yview moveto 1

  proc test {{change false}} {
  global content t
      set fraction [lindex [.t yview] 0]
      puts "offscreen: $fraction"
      set old [.t get 1.0 end]
      if {$change} {
          .t delete 1.0 end
          .t insert 1.0 $content
      .t yview moveto $fraction
      puts "offscreen: [lindex [.t yview] 0]"
      if {[expr {$old eq [.t get 1.0 end]}]} {
          puts "text stayed the same"
      } else {
          puts "text has changed"

  test 1


1. If proc test is executed (copied/pasted) line by line, then there is no bug.

2. If the text widget is configured with -wrap none, there is no bug.

The difference between the two calls 'test false' and 'test true' comes from the asynchronous calculation of the lines height in pixels. This calculation may not yet be finished when '.t yview moveto $fraction' is called. This is true whether or not an update has been called: this asynchronous calculation of pixel heigths is disconnected from the display refresh and from the event loop (i.e. update commands).

Because of that, TkTextYviewCmd: 5947:
    int numPixels = TkBTreeNumPixels(textPtr->sharedTextPtr->tree,textPtr);
returns a total number of pixels that is too small, whereas it should reflect the total number of pixels necessary to display _all_ lines.

Not sure what can be done to change this behavior, it's tricky.
Forcing full update of the text widget lines heights is certainly not the thing to do if we want to keep a minimum of performance...

mbroeken added on 2006-09-28 17:30:12:
File Added - 195616: yview2.tcl