Updated 2011-11-08 16:57:13 by DRB

[ adavis ] I am developing an application which requires a third mouse button; However, the two button mouse seems by far to be the most common variety. I've put together something which emulates a third mouse button by pressing both mouse buttons together. I've searched but haven't found an existing solution (though I guess there must be one) so I'm posting my version. It seems to work OK but I presume there is a neater solution...

I've decided to call the system button13 which generates the following virtual events:-

  • <<Button-1>> - Button one pressed.
  • <<Button-3>> - Button three pressed.
  • <<Button-13>> - Buttons one and three pressed together.

Buttons one and three must be pressed within 200ms of each other (This value can be set as a parameter).
 proc button13 {widget {ms 200}} {
    bind $widget <Button-1> "button13proc1 $widget 1 $ms"
    bind $widget <Button-3> "button13proc1 $widget 3 $ms"
 }

 proc button13proc1 {widget button ms} {
    global button13

    if {[info exists button13($widget)] && ! [string equal $button13($widget) $button]} {
       event generate $widget <<Button-13>>
       catch "unset button13($widget)"
       return
    }

    set button13($widget) $button

    after $ms "button13proc2 $widget $button"
 }

 proc button13proc2 {widget button} {
    global button13

    if {! [info exists button13($widget)]} {
       return
    }

    if {[info exists button13($widget)] && ! [string equal $button13($widget) $button]} {
       event generate $widget <<Button-13>>
    } else {
       event generate $widget <<Button-$button>>
    }

    catch "unset button13($widget)"
 }

 #===================#
 # Example of usage. #
 #===================#

 label .lab1 -text "Click on this label"

 button13 .lab1

 bind .lab1 <<Button-1>>  "puts Button-1"
 bind .lab1 <<Button-3>>  "puts Button-3"
 bind .lab1 <<Button-13>> "puts Button-13"

 pack .lab1

While this is clearly useful, I disagree that the majority of mice are two-button. 80% of mice sold have a mouse wheel (which doubles as a middle button), and I'm sure a good deal of the others have a standard button for the third. -FW

adavis: You're right, but there still seem to be a lot of "legacy mice" out there. We have about 8000 PCs and still by far the majority are two button. When they've all been replaced, say a couple of years, we'll be into the 21st century!! Maybe our organisation is not particularly representative (A bad assumption on my part).

GPS: This seems simpler:
 bind . <Button-1><Button-3> {puts 2}
 bind . <Button-3><Button-1> {puts 2}

In practice I would proc'ify it, but you probably get the idea. It would need a single variable to record the state, because if 1 and 3 are activated and then released, and 1 is pressed again the <Button-3><Button-1> binding will be invoked.

adavis: I also want to check independantly for <Button-1> and <Button-3> events. I'm not sure how I would do this without having some kind of timeout mechinism?

FW: Also, doesn't X have an option to implement this automatically? I remember being asked about this option in more than one Linux install, IIRC.

Duoas: Yes, I know this page is really old, but I wonder how many people still struggle with cross-platform mouse possibilities? I wrote a little package that I like to use. I've been meaning to make it available to others for a while now, so here it is. VirtualMouse Cross Platform Mouse Handling

DRB 2011-11-08 : I found this really helpful for making a scale that would respond to left and right mouse clicks and motion keys, but "lock in" the selected value when both are pressed. Thanks!