3 # This file defines the default bindings for Tk label, button,
4 # checkbutton, and radiobutton widgets and provides procedures
5 # that help in implementing those bindings.
7 # Copyright (c) 1992-1994 The Regents of the University of California.
8 # Copyright (c) 1994-1996 Sun Microsystems, Inc.
9 # Copyright (c) 2002 ActiveState Corporation.
11 # See the file "license.terms" for information on usage and redistribution
12 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 #-------------------------------------------------------------------------
16 # The code below creates the default class bindings for buttons.
17 #-------------------------------------------------------------------------
19 if {[tk windowingsystem] eq "aqua"} {
21 bind Radiobutton <Enter> {
24 bind Radiobutton <1> {
27 bind Radiobutton <ButtonRelease-1> {
30 bind Checkbutton <Enter> {
33 bind Checkbutton <1> {
36 bind Checkbutton <ButtonRelease-1> {
39 bind Checkbutton <Leave> {
43 if {"win32" eq [tk windowingsystem]} {
44 bind Checkbutton <equal> {
45 tk::CheckRadioInvoke %W select
47 bind Checkbutton <plus> {
48 tk::CheckRadioInvoke %W select
50 bind Checkbutton <minus> {
51 tk::CheckRadioInvoke %W deselect
53 bind Checkbutton <1> {
56 bind Checkbutton <ButtonRelease-1> {
59 bind Checkbutton <Enter> {
60 tk::CheckRadioEnter %W
62 bind Checkbutton <Leave> {
66 bind Radiobutton <1> {
69 bind Radiobutton <ButtonRelease-1> {
72 bind Radiobutton <Enter> {
73 tk::CheckRadioEnter %W
76 if {"x11" eq [tk windowingsystem]} {
77 bind Checkbutton <Return> {
78 if {!$tk_strictMotif} {
82 bind Radiobutton <Return> {
83 if {!$tk_strictMotif} {
84 tk::CheckRadioInvoke %W
87 bind Checkbutton <1> {
90 bind Radiobutton <1> {
91 tk::CheckRadioInvoke %W
93 bind Checkbutton <Enter> {
96 bind Radiobutton <Enter> {
99 bind Checkbutton <Leave> {
104 bind Button <space> {
107 bind Checkbutton <space> {
108 tk::CheckRadioInvoke %W
110 bind Radiobutton <space> {
111 tk::CheckRadioInvoke %W
113 bind Button <<Invoke>> {
116 bind Checkbutton <<Invoke>> {
117 tk::CheckRadioInvoke %W
119 bind Radiobutton <<Invoke>> {
120 tk::CheckRadioInvoke %W
123 bind Button <FocusIn> {}
124 bind Button <Enter> {
127 bind Button <Leave> {
133 bind Button <ButtonRelease-1> {
137 bind Checkbutton <FocusIn> {}
139 bind Radiobutton <FocusIn> {}
140 bind Radiobutton <Leave> {
144 if {"win32" eq [tk windowingsystem]} {
146 #########################
147 # Windows implementation
148 #########################
150 # ::tk::ButtonEnter --
151 # The procedure below is invoked when the mouse pointer enters a
152 # button widget. It records the button we're in and changes the
153 # state of the button to active unless the button is disabled.
156 # w - The name of the widget.
158 proc ::tk::ButtonEnter w {
160 if {[$w cget -state] ne "disabled"} {
162 # If the mouse button is down, set the relief to sunken on entry.
163 # Overwise, if there's an -overrelief value, set the relief to that.
165 set Priv($w,relief) [$w cget -relief]
166 if {$Priv(buttonWindow) eq $w} {
167 $w configure -relief sunken -state active
168 set Priv($w,prelief) sunken
169 } elseif {[set over [$w cget -overrelief]] ne ""} {
170 $w configure -relief $over
171 set Priv($w,prelief) $over
177 # ::tk::ButtonLeave --
178 # The procedure below is invoked when the mouse pointer leaves a
179 # button widget. It changes the state of the button back to inactive.
180 # Restore any modified relief too.
183 # w - The name of the widget.
185 proc ::tk::ButtonLeave w {
187 if {[$w cget -state] ne "disabled"} {
188 $w configure -state normal
191 # Restore the original button relief if it was changed by Tk.
192 # That is signaled by the existence of Priv($w,prelief).
194 if {[info exists Priv($w,relief)]} {
195 if {[info exists Priv($w,prelief)] && \
196 $Priv($w,prelief) eq [$w cget -relief]} {
197 $w configure -relief $Priv($w,relief)
199 unset -nocomplain Priv($w,relief) Priv($w,prelief)
205 # ::tk::ButtonDown --
206 # The procedure below is invoked when the mouse button is pressed in
207 # a button widget. It records the fact that the mouse is in the button,
208 # saves the button's relief so it can be restored later, and changes
209 # the relief to sunken.
212 # w - The name of the widget.
214 proc ::tk::ButtonDown w {
217 # Only save the button's relief if it does not yet exist. If there
218 # is an overrelief setting, Priv($w,relief) will already have been set,
219 # and the current value of the -relief option will be incorrect.
221 if {![info exists Priv($w,relief)]} {
222 set Priv($w,relief) [$w cget -relief]
225 if {[$w cget -state] ne "disabled"} {
226 set Priv(buttonWindow) $w
227 $w configure -relief sunken -state active
228 set Priv($w,prelief) sunken
230 # If this button has a repeatdelay set up, get it going with an after
231 after cancel $Priv(afterId)
232 set delay [$w cget -repeatdelay]
235 set Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]
241 # The procedure below is invoked when the mouse button is released
242 # in a button widget. It restores the button's relief and invokes
243 # the command as long as the mouse hasn't left the button.
246 # w - The name of the widget.
248 proc ::tk::ButtonUp w {
250 if {$Priv(buttonWindow) eq $w} {
251 set Priv(buttonWindow) ""
253 # Restore the button's relief if it was cached.
255 if {[info exists Priv($w,relief)]} {
256 if {[info exists Priv($w,prelief)] && \
257 $Priv($w,prelief) eq [$w cget -relief]} {
258 $w configure -relief $Priv($w,relief)
260 unset -nocomplain Priv($w,relief) Priv($w,prelief)
263 # Clean up the after event from the auto-repeater
264 after cancel $Priv(afterId)
266 if {$Priv(window) eq $w && [$w cget -state] ne "disabled"} {
267 $w configure -state normal
269 # Only invoke the command if it wasn't already invoked by the
270 # auto-repeater functionality
271 if { $Priv(repeated) == 0 } {
272 uplevel #0 [list $w invoke]
278 # ::tk::CheckRadioEnter --
279 # The procedure below is invoked when the mouse pointer enters a
280 # checkbutton or radiobutton widget. It records the button we're in
281 # and changes the state of the button to active unless the button is
285 # w - The name of the widget.
287 proc ::tk::CheckRadioEnter w {
289 if {[$w cget -state] ne "disabled"} {
290 if {$Priv(buttonWindow) eq $w} {
291 $w configure -state active
293 if {[set over [$w cget -overrelief]] ne ""} {
294 set Priv($w,relief) [$w cget -relief]
295 set Priv($w,prelief) $over
296 $w configure -relief $over
302 # ::tk::CheckRadioDown --
303 # The procedure below is invoked when the mouse button is pressed in
304 # a button widget. It records the fact that the mouse is in the button,
305 # saves the button's relief so it can be restored later, and changes
306 # the relief to sunken.
309 # w - The name of the widget.
311 proc ::tk::CheckRadioDown w {
313 if {![info exists Priv($w,relief)]} {
314 set Priv($w,relief) [$w cget -relief]
316 if {[$w cget -state] ne "disabled"} {
317 set Priv(buttonWindow) $w
319 $w configure -state active
325 if {"x11" eq [tk windowingsystem]} {
327 #####################
328 # Unix implementation
329 #####################
331 # ::tk::ButtonEnter --
332 # The procedure below is invoked when the mouse pointer enters a
333 # button widget. It records the button we're in and changes the
334 # state of the button to active unless the button is disabled.
337 # w - The name of the widget.
339 proc ::tk::ButtonEnter {w} {
341 if {[$w cget -state] ne "disabled"} {
342 # On unix the state is active just with mouse-over
343 $w configure -state active
345 # If the mouse button is down, set the relief to sunken on entry.
346 # Overwise, if there's an -overrelief value, set the relief to that.
348 set Priv($w,relief) [$w cget -relief]
349 if {$Priv(buttonWindow) eq $w} {
350 $w configure -relief sunken
351 set Priv($w,prelief) sunken
352 } elseif {[set over [$w cget -overrelief]] ne ""} {
353 $w configure -relief $over
354 set Priv($w,prelief) $over
360 # ::tk::ButtonLeave --
361 # The procedure below is invoked when the mouse pointer leaves a
362 # button widget. It changes the state of the button back to inactive.
363 # Restore any modified relief too.
366 # w - The name of the widget.
368 proc ::tk::ButtonLeave w {
370 if {[$w cget -state] ne "disabled"} {
371 $w configure -state normal
374 # Restore the original button relief if it was changed by Tk.
375 # That is signaled by the existence of Priv($w,prelief).
377 if {[info exists Priv($w,relief)]} {
378 if {[info exists Priv($w,prelief)] && \
379 $Priv($w,prelief) eq [$w cget -relief]} {
380 $w configure -relief $Priv($w,relief)
382 unset -nocomplain Priv($w,relief) Priv($w,prelief)
388 # ::tk::ButtonDown --
389 # The procedure below is invoked when the mouse button is pressed in
390 # a button widget. It records the fact that the mouse is in the button,
391 # saves the button's relief so it can be restored later, and changes
392 # the relief to sunken.
395 # w - The name of the widget.
397 proc ::tk::ButtonDown w {
400 # Only save the button's relief if it does not yet exist. If there
401 # is an overrelief setting, Priv($w,relief) will already have been set,
402 # and the current value of the -relief option will be incorrect.
404 if {![info exists Priv($w,relief)]} {
405 set Priv($w,relief) [$w cget -relief]
408 if {[$w cget -state] ne "disabled"} {
409 set Priv(buttonWindow) $w
410 $w configure -relief sunken
411 set Priv($w,prelief) sunken
413 # If this button has a repeatdelay set up, get it going with an after
414 after cancel $Priv(afterId)
415 set delay [$w cget -repeatdelay]
418 set Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]
424 # The procedure below is invoked when the mouse button is released
425 # in a button widget. It restores the button's relief and invokes
426 # the command as long as the mouse hasn't left the button.
429 # w - The name of the widget.
431 proc ::tk::ButtonUp w {
433 if {$w eq $Priv(buttonWindow)} {
434 set Priv(buttonWindow) ""
436 # Restore the button's relief if it was cached.
438 if {[info exists Priv($w,relief)]} {
439 if {[info exists Priv($w,prelief)] && \
440 $Priv($w,prelief) eq [$w cget -relief]} {
441 $w configure -relief $Priv($w,relief)
443 unset -nocomplain Priv($w,relief) Priv($w,prelief)
446 # Clean up the after event from the auto-repeater
447 after cancel $Priv(afterId)
449 if {$Priv(window) eq $w && [$w cget -state] ne "disabled"} {
450 # Only invoke the command if it wasn't already invoked by the
451 # auto-repeater functionality
452 if { $Priv(repeated) == 0 } {
453 uplevel #0 [list $w invoke]
461 if {[tk windowingsystem] eq "aqua"} {
467 # ::tk::ButtonEnter --
468 # The procedure below is invoked when the mouse pointer enters a
469 # button widget. It records the button we're in and changes the
470 # state of the button to active unless the button is disabled.
473 # w - The name of the widget.
475 proc ::tk::ButtonEnter {w} {
477 if {[$w cget -state] ne "disabled"} {
479 # If there's an -overrelief value, set the relief to that.
481 if {$Priv(buttonWindow) eq $w} {
482 $w configure -state active
483 } elseif {[set over [$w cget -overrelief]] ne ""} {
484 set Priv($w,relief) [$w cget -relief]
485 set Priv($w,prelief) $over
486 $w configure -relief $over
492 # ::tk::ButtonLeave --
493 # The procedure below is invoked when the mouse pointer leaves a
494 # button widget. It changes the state of the button back to
495 # inactive. If we're leaving the button window with a mouse button
496 # pressed (Priv(buttonWindow) == $w), restore the relief of the
500 # w - The name of the widget.
502 proc ::tk::ButtonLeave w {
504 if {$w eq $Priv(buttonWindow)} {
505 $w configure -state normal
508 # Restore the original button relief if it was changed by Tk.
509 # That is signaled by the existence of Priv($w,prelief).
511 if {[info exists Priv($w,relief)]} {
512 if {[info exists Priv($w,prelief)] && \
513 $Priv($w,prelief) eq [$w cget -relief]} {
514 $w configure -relief $Priv($w,relief)
516 unset -nocomplain Priv($w,relief) Priv($w,prelief)
522 # ::tk::ButtonDown --
523 # The procedure below is invoked when the mouse button is pressed in
524 # a button widget. It records the fact that the mouse is in the button,
525 # saves the button's relief so it can be restored later, and changes
526 # the relief to sunken.
529 # w - The name of the widget.
531 proc ::tk::ButtonDown w {
534 if {[$w cget -state] ne "disabled"} {
535 set Priv(buttonWindow) $w
536 $w configure -state active
538 # If this button has a repeatdelay set up, get it going with an after
539 after cancel $Priv(afterId)
541 if { ![catch {$w cget -repeatdelay} delay] } {
543 set Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]
550 # The procedure below is invoked when the mouse button is released
551 # in a button widget. It restores the button's relief and invokes
552 # the command as long as the mouse hasn't left the button.
555 # w - The name of the widget.
557 proc ::tk::ButtonUp w {
559 if {$Priv(buttonWindow) eq $w} {
560 set Priv(buttonWindow) ""
561 $w configure -state normal
563 # Restore the button's relief if it was cached.
565 if {[info exists Priv($w,relief)]} {
566 if {[info exists Priv($w,prelief)] && \
567 $Priv($w,prelief) eq [$w cget -relief]} {
568 $w configure -relief $Priv($w,relief)
570 unset -nocomplain Priv($w,relief) Priv($w,prelief)
573 # Clean up the after event from the auto-repeater
574 after cancel $Priv(afterId)
576 if {$Priv(window) eq $w && [$w cget -state] ne "disabled"} {
577 # Only invoke the command if it wasn't already invoked by the
578 # auto-repeater functionality
579 if { $Priv(repeated) == 0 } {
580 uplevel #0 [list $w invoke]
592 # ::tk::ButtonInvoke --
593 # The procedure below is called when a button is invoked through
594 # the keyboard. It simulate a press of the button via the mouse.
597 # w - The name of the widget.
599 proc ::tk::ButtonInvoke w {
600 if {[winfo exists $w] && [$w cget -state] ne "disabled"} {
601 set oldRelief [$w cget -relief]
602 set oldState [$w cget -state]
603 $w configure -state active -relief sunken
604 after 100 [list ::tk::ButtonInvokeEnd $w $oldState $oldRelief]
608 # ::tk::ButtonInvokeEnd --
609 # The procedure below is called after a button is invoked through
610 # the keyboard. It simulate a release of the button via the mouse.
613 # w - The name of the widget.
614 # oldState - Old state to be set back.
615 # oldRelief - Old relief to be set back.
617 proc ::tk::ButtonInvokeEnd {w oldState oldRelief} {
618 if {[winfo exists $w]} {
619 $w configure -state $oldState -relief $oldRelief
620 uplevel #0 [list $w invoke]
624 # ::tk::ButtonAutoInvoke --
626 # Invoke an auto-repeating button, and set it up to continue to repeat.
629 # w button to invoke.
635 # May create an after event to call ::tk::ButtonAutoInvoke.
637 proc ::tk::ButtonAutoInvoke {w} {
639 after cancel $Priv(afterId)
640 set delay [$w cget -repeatinterval]
641 if {$Priv(window) eq $w} {
643 uplevel #0 [list $w invoke]
646 set Priv(afterId) [after $delay [list tk::ButtonAutoInvoke $w]]
650 # ::tk::CheckRadioInvoke --
651 # The procedure below is invoked when the mouse button is pressed in
652 # a checkbutton or radiobutton widget, or when the widget is invoked
653 # through the keyboard. It invokes the widget if it
657 # w - The name of the widget.
658 # cmd - The subcommand to invoke (one of invoke, select, or deselect).
660 proc ::tk::CheckRadioInvoke {w {cmd invoke}} {
661 if {[$w cget -state] ne "disabled"} {
662 uplevel #0 [list $w $cmd]
666 # Special versions of the handlers for checkbuttons on Unix that do the magic
667 # to make things work right when the checkbutton indicator is hidden;
668 # radiobuttons don't need this complexity.
670 # ::tk::CheckInvoke --
671 # The procedure below invokes the checkbutton, like ButtonInvoke, but handles
672 # what to do when the checkbutton indicator is missing. Only used on Unix.
675 # w - The name of the widget.
677 proc ::tk::CheckInvoke {w} {
679 if {[$w cget -state] ne "disabled"} {
680 # Additional logic to switch the "selected" colors around if necessary
681 # (when we're indicator-less).
683 if {![$w cget -indicatoron] && [info exist Priv($w,selectcolor)]} {
684 if {[$w cget -selectcolor] eq $Priv($w,aselectcolor)} {
685 $w configure -selectcolor $Priv($w,selectcolor)
687 $w configure -selectcolor $Priv($w,aselectcolor)
690 uplevel #0 [list $w invoke]
694 # ::tk::CheckEnter --
695 # The procedure below enters the checkbutton, like ButtonEnter, but handles
696 # what to do when the checkbutton indicator is missing. Only used on Unix.
699 # w - The name of the widget.
701 proc ::tk::CheckEnter {w} {
703 if {[$w cget -state] ne "disabled"} {
704 # On unix the state is active just with mouse-over
705 $w configure -state active
707 # If the mouse button is down, set the relief to sunken on entry.
708 # Overwise, if there's an -overrelief value, set the relief to that.
710 set Priv($w,relief) [$w cget -relief]
711 if {$Priv(buttonWindow) eq $w} {
712 $w configure -relief sunken
713 set Priv($w,prelief) sunken
714 } elseif {[set over [$w cget -overrelief]] ne ""} {
715 $w configure -relief $over
716 set Priv($w,prelief) $over
719 # Compute what the "selected and active" color should be.
721 if {![$w cget -indicatoron] && [$w cget -selectcolor] ne ""} {
722 set Priv($w,selectcolor) [$w cget -selectcolor]
723 lassign [winfo rgb $w [$w cget -selectcolor]] r1 g1 b1
724 lassign [winfo rgb $w [$w cget -activebackground]] r2 g2 b2
725 set Priv($w,aselectcolor) \
726 [format "#%04x%04x%04x" [expr {($r1+$r2)/2}] \
727 [expr {($g1+$g2)/2}] [expr {($b1+$b2)/2}]]
728 # use uplevel to work with other var resolvers
729 if {[uplevel #0 [list set [$w cget -variable]]]
730 eq [$w cget -onvalue]} {
731 $w configure -selectcolor $Priv($w,aselectcolor)
738 # ::tk::CheckLeave --
739 # The procedure below leaves the checkbutton, like ButtonLeave, but handles
740 # what to do when the checkbutton indicator is missing. Only used on Unix.
743 # w - The name of the widget.
745 proc ::tk::CheckLeave {w} {
747 if {[$w cget -state] ne "disabled"} {
748 $w configure -state normal
751 # Restore the original button "selected" color; but only if the user
752 # has not changed it in the meantime.
754 if {![$w cget -indicatoron] && [info exist Priv($w,selectcolor)]} {
755 if {[$w cget -selectcolor] eq $Priv($w,selectcolor)
756 || ([info exist Priv($w,aselectcolor)] &&
757 [$w cget -selectcolor] eq $Priv($w,aselectcolor))} {
758 $w configure -selectcolor $Priv($w,selectcolor)
761 unset -nocomplain Priv($w,selectcolor) Priv($w,aselectcolor)
763 # Restore the original button relief if it was changed by Tk. That is
764 # signaled by the existence of Priv($w,prelief).
766 if {[info exists Priv($w,relief)]} {
767 if {[info exists Priv($w,prelief)] && \
768 $Priv($w,prelief) eq [$w cget -relief]} {
769 $w configure -relief $Priv($w,relief)
771 unset -nocomplain Priv($w,relief) Priv($w,prelief)