Text Widget Bug

MG, on June 8th 2005

Um, is this reported in the Tk Bug Tracker? http://sourceforge.net/tracker/?group_id=12997&atid=112997

MG I've just skimmed the list, and can't see it there, no. I'm not entirely sure it is actually a Tk bug, though - we're both running the same OS, and the same version of (Active)Tcl/Tk, but I can't get the problem on my computer, doing exactly the same thing he's doing. I'll do some more testing as suggested below, and see if I can replicate it any other way (either on this computer, or on his outside of this particular Tcl program), and see what I can find out...

Hey folks,

A friend of mine using a Tcl/Tk program I wrote (Potato MUSH (MUD) Client) seems to have found a bug in the text widget, but it's one I can't to replicate (I'm using ActiveTcl 8.4.9). The text widget has a few modified bindings, but the only one which could be relevant to this is a new <MouseWheel> binding:

  bind Text <MouseWheel> {mouseWheel %W %X %Y %D}
  proc mouseWheel {w x y d} {

    set in [winfo containing -displayof $w $x $y]
    if { $in == "" || [winfo class $in] != "Text" } {
         $w yview scroll [expr {- ($d / 120) * 4}] units
       } else {
         $in yview scroll [expr {- ($d / 120) * 4}] units
  };# mouseWheel

When he scrolls with the middle button (a wheel mouse), the display of the Text widget becomes, for lack of a better word, "screwy". A couple of screen shots (before and after scrolling) are below, along with some info on his computer / Tcl version.. if anyone has any ideas, about whether this is a bug in the Text widget or something in my code, I'd appreciate any help.


(My apologies for the huge images, btw - I didn't want to shrink them for risk of losing clarity)

escargo 8 Jun 2005 - Maybe you could build a test version and use event generate to simulate mousewheel movement and see if you can duplicate the problem.

MG Yeah, that's a good idea - can't think why it never occurred to me, now that you've said it :) I'll do some experimenting and see what I can find... There isn't a way to bind to any and all events, is there? I know you can, for instance, bind to <Key> for all keypress events, but I don't know of a catch-all binding (for the purposes of bind $textWidget <All> {puts %K} to see exactly what's firing).

 % set tcl_patchLevel
 % set tk_patchLevel
 % parray tcl_platform
 tcl_platform(byteOrder) = littleEndian
 tcl_platform(machine)   = intel
 tcl_platform(os)        = Windows NT
 tcl_platform(osVersion) = 5.1
 tcl_platform(platform)  = windows
 tcl_platform(user)      = The Master
 tcl_platform(wordSize)  = 4

Peter Newman 9 June 2005: From the bind manpage:-

  • %X - The x_root field from the event. If a virtual-root window manager is being used then the substituted value is the corresponding x-coordinate in the virtual root. Valid only for ButtonPress, ButtonRelease, KeyPress, KeyRelease, and Motion events.
  • %Y - The y_root field from the event. If a virtual-root window manager is being used then the substituted value is the corresponding y-coordinate in the virtual root. Valid only for ButtonPress, ButtonRelease, KeyPress, KeyRelease, and Motion events.

Doesn't this mean that %X and %Y aren't supported by the <MouseWheel> event?

MG Running wish and typing

 bind . <MouseWheel> {puts "%W %X %Y %D"}

into the console, it looks like it actually does. I moved the mouse around over '.', scrolling the mousewheel, and it printed to the console just what I expected:

 . 305 310 -360
 . 272 326 -360
 . 269 311 -360
 . 255 300 -360

I will get him to try and recreate the problem without the modified <MouseWheel> binding as soon as I see him, though, and see if he still sees the problem.

MG on June 13 2005 It looks like I've found what's causing the problem - it's not <MouseWheel> at all, it's the bindings on Button-2. When you press Button-2 (which is, for non-scrolling purposes, what the mouse wheel is) and move the mouse, it scrolls the text widget. When you press it and release it without moving the mouse, it pastes the entire selection of the text widget in question (if any) where you click. This appears to all be done by the

 $textWidget scan mark $x $y

command (or at least, that's what the <Button-2> binding does, and I can't find anything else that's firing here).. and unless I'm mis-reading the docs, it shouldn't be doing this. Can anyone with more knowledge about this confirm it, before I add it into the Tk bug tracker? Running this script -should- produce the problem, with any 3-button or wheel- mouse...

  pack [text .t -width 80] -side left -expand 1
  .t insert end [string repeat "abcdefg123456789 " 10]

Now just select some text in whichever way you usually would, place the mouse over any piece of text in the widget (doesn't have to be over the selection), and click the middle button / mouse (don't move the mouse, between ButtonPress and ButtonRelease).

Looking forward to hearing whether anyone else sees this...

DKF: Cool! It supports xterm-style PRIMARY pasting!

To explain, it's been specifically programmed that way because the Unix application xterm uses the middle button of a classic 3-button mouse to indicate that the PRIMARY selection should be pasted. Tk's just copying that (and it's not a bad choice really; mouse-driven mark-and-paste is a much more efficient way of operating than the Mac/CUA/Win Ctrl-X/C/V combo). This is achieved through the following binding (from 8.4):

 bind Text <<PasteSelection>> {
     if {$tk_strictMotif || ![info exists tk::Priv(mouseMoved)]
         || !$tk::Priv(mouseMoved)} {
         tk::TextPasteSelection %W %x %y

Adding the following widget-specific binding will prevent this for any widget you want:

 bind .myText <<PasteSelection>> { break }

MG Wow. That's a ridiculously simple answer, when you know it. Thanks very much, DKF. :)