Author: Csaba Nemethi <csaba.nemethi@t-online.de>
State: Final
Type: Project
Tcl-Version: 9.1
Vote: Done
Created: 04-Nov-2025
Keywords: mouse wheel, touchpad, scroll, event, binding, entry
Tk-Branch: tip-736
Vote-Summary: Accepted 8/0/0
Votes-For: HO, JN, KW, SL, RA, MC, APN, AK
Votes-Against: none
Votes-Present: none
Abstract
This TIP proposes to add mouse wheel and <TouchpadScroll>
event bindings for the widget classes Entry and
TEntry. The binding scripts should scroll the entry or
ttk::entry widget by invoking
its xview scroll amount units subcommand.
Rationale
René Zaumseil proposed recently on Tcl Core List to add the following bindings to Tk:
bind Entry <MouseWheel> {tk::MouseWheel %W x %D -40.0 units}
bind TEntry <MouseWheel> {tk::MouseWheel %W x %D -40.0 units}
The binding script above translates to
%W xview scroll [expr {%D/-40.0}] units
While it is surely a good idea to enable the user to scroll an entry or
ttk::entry widget with the mouse wheel, the binding script proposed by René
needs several adaptations so it can properly handle two-finger touchpad
gestures, which on x11 give rise to intermixed
<MouseWheel> and <Shift-MouseWheel> events.
In addition, an extra binding for <TouchpadScroll> events is
needed for handling two-finger gestures on win32 and
aqua.
This TIP aims at adapting René's proposal in such a way that it works as expected with both the mouse wheel and the touchpad, on all three windowing systems.
Specification
The TIP proposes to add the following bindings to the file
library/entry.tcl:
bind Entry <Enter> {+
set tk::Priv(xWheelEvents) 0; set tk::Priv(yWheelEvents) 0
}
bind Entry <MouseWheel> {
tk::EntryScrollByUnits %W y %D -40.0
}
bind Entry <Option-MouseWheel> {
tk::EntryScrollByUnits %W y %D -12.0
}
bind Entry <Shift-MouseWheel> {
tk::EntryScrollByUnits %W x %D -40.0
}
bind Entry <Shift-Option-MouseWheel> {
tk::EntryScrollByUnits %W x %D -12.0
}
bind Entry <TouchpadScroll> {
if {%# %% 5 == 0} {
lassign [tk::PreciseScrollDeltas %D] tk::Priv(deltaX) tk::Priv(deltaY)
if {$tk::Priv(deltaX) != 0} {
%W xview scroll [expr {-$tk::Priv(deltaX)}] units
}
}
}
# ::tk::EntryScrollByUnits --
#
# Scrolls the entry by units.
#
# Arguments:
# w - The entry window that received a mouse wheel event.
# axis - x if the event contains the Shift modifier and y otherwise.
# amount - Delta value from the mouse wheel event.
# factor - $amount/$factor = number of scroll units for $w xview scroll.
proc ::tk::EntryScrollByUnits {w axis amount factor} {
# Count both the <MouseWheel> and <Shift-MouseWheel>
# events, and ignore the non-dominant ones
variable ::tk::Priv
incr Priv(${axis}WheelEvents)
if {($Priv(xWheelEvents) + $Priv(yWheelEvents) > 10) &&
($axis eq "x" && $Priv(xWheelEvents) < $Priv(yWheelEvents) ||
$axis eq "y" && $Priv(yWheelEvents) < $Priv(xWheelEvents))} {
return
}
tk::MouseWheel $w x $amount $factor units
}
Further, create similar bindings for the widget class TEntry
by adding the following lines to the file library/ttk/entry.tcl:
# Copy the mouse wheel event bindings from Entry to TEntry
#
bind TEntry <Enter> {+
set tk::Priv(xWheelEvents) 0; set tk::Priv(yWheelEvents) 0
}
foreach event {<MouseWheel> <Option-MouseWheel>
<Shift-MouseWheel> <Shift-Option-MouseWheel>
<TouchpadScroll>} {
bind TEntry $event [bind Entry $event]
}
unset event
Reference Implementation
A ready-to-use reference implementation can be found in the Tk branch
tip-736. Besides the
already mentioned files library/entry.tcl and
library/ttk/entry.tcl, it contains also slightly modified versions
of library/ttk/combobox.tcl and
library/ttk/spinbox.tcl, needed because the widget classes
TCombobox and TSpinbox inherit (and partly
override) the TEntry bindings.
Copyright
This document has been placed in the public domain.