TIP 474: Treat the mouse wheel events in a uniform way

Bounty program for improvements to Tcl and certain Tcl packages.
Author:	Arjen Markus <[email protected]>
State:	Draft
Type:	Project
Vote:	Pending
Created:	25-Aug-2017
Post-history:	PM
Tcl-Version:	8.6
Keywords:	Tk, events
Tk-Branch:	tip474-uniform-mouse-wheel


This TIP proposes to treat the mouse wheel events on all platforms in a similar way. Currently, a program running on Windows should bind to "MouseWheel" events, whereas a program running on Linux should bind to "ButtonPress-4" and "ButtonPress-5" commands. This makes it somewhat awkward to support both types of platforms.


Tk provides a means to define user-interfaces using code that is almost perfectly independent of the platform that the program should run on. It therefore makes sens that the treatment of user actions, such as mouse clicks and the use of the mouse wheel should be independent of the platform as well. Currently, however, "Windows-type" and OSX platforms support the "MouseWheel" event, whereas for "Linux-type" platforms the program should bind to "ButtonPress-4" and "ButtonPress-5" events. This is in contrast to almost all other events and event bindings.

The documentation in its present form only describes the "MouseWheel" form.

Current behaviour

The code fragment below illustrates the behaviour: run it under various platforms and use the mouse wheel in the canvas window to see which bindings fired.

pack [canvas .c]

catch {console show}

bind .c <ButtonPress> [list puts "ButtonPress %W %b"]
bind .c <Shift-ButtonPress> [list puts "Shift-ButtonPress %W %b"]
bind .c <Control-ButtonPress> [list puts "Control-ButtonPress %W %b"]
bind .c <MouseWheel> [list puts "MouseWheel %W %D"]
bind .c <Shift-MouseWheel> [list puts "Shift-MouseWheel %W %D"]
bind .c <Control-MouseWheel> [list puts "Control-MouseWheel %W %D"]


This TIP proposes to extend the bindings for the mouse wheel in such a way that it does not matter which platform the program runs on. To keep the incompatibility due to this change to a minimum, both types of bindings might hold on both types of events:

bind widget "ButtonPress-4" cmd
bind widget "MouseWheel" cmd

(One caveat is in the direction of the mouse wheel - using the first, one selects the direction via the button number: 4 for "up" and 5 for "down", whereas in the second form the %D substitution has to be used.)

It is simpler, however, to translate the "Button 4" and "Button 5" events to equivalent "Mousewheel" events. This can be introduced for Tcl/Tk 8.7. The modifiers "Control" and "Shift" should be supported analogously.

As an example (thanks to Jan Nijtmans for this), the bindings for the text widget would look like this:

bind Text <MouseWheel> {
    %W yview scroll %D pixels
bind Text <Option-MouseWheel> {
    %W yview scroll %D pixels
bind Text <Shift-MouseWheel> {
    %W xview scroll %D pixels
bind Text <Shift-Option-MouseWheel> {
    %W xview scroll %D pixels

with the %D substitution giving the right amount of pixels.

Considerations regarding the incompatibility

An application that currently uses the "ButtonPress-4/5" events needs to be changed to use the "MouseWheel" events regardless of platform.

If the application needs to support Tcl/Tk 8.6, an extra check is required to decide which events to listen to: a Linux-like platform together with Tk 8.6, instead of simply a Linux-like platform.

This seems a minor inconvenience for gaining further platform-independence.

Reference Implementation

In tk branch tip474-uniform-mouse-wheel.


This document is placed in public domain.