event(n)
π event(n) π
okay bestie, this one lives in the Tk Built-In Commands manual, and it's genuinely the backbone of how Tk handles window system events. it's long, so buckle up π
β¨ SYNOPSIS β¨
event option ?arg ...?
πΈ DESCRIPTION πΈ
so the event command is basically your little toolkit for dealing with window system events β the real ones, the fake ones, the "what even is an event" ones. it gives you several facilities: defining virtual events and synthesizing events (yes, you can just make an event happen, main character energy fr fr π).
the command has several different forms, and which one you get is determined by the first argument. here's everything that's currently supported:
event add <<virtual>> sequence ?sequence ...?β this one associates the virtual event virtual with the physical event sequence(s) you pass in the sequence arguments, so that the virtual event triggers whenever any one of those sequences occurs. Virtual can be any string value, and sequence can have any of the values allowed for thesequenceargument to thebindcommand. and if virtual is already defined? no worries, the new physical event sequences just add to the existing sequences for that event. slay, additive πevent delete <<virtual>> ?sequence sequence ...?β the breakup form. it deletes each of the sequences from those associated with the virtual event given by virtual. Virtual can be any string value, and sequence can have any of the values allowed for thesequenceargument to thebindcommand. any sequences not currently associated with virtual are just ignored (no drama, they weren't invited anyway π). and if you pass no sequence argument at all, then all physical event sequences are removed for virtual, so that virtual event will simply never trigger again. it's giving "we're done here" πevent generate window event ?option value option value ...?β the iconic one. synthetic events, no cap. it generates a window event and arranges for it to be processed just as if it had come from the window system β the whole app is fooled, it ate π. Window gives the path name of the window for which the event will be generated; it may also be an identifier (such as the one returned bywinfo id) as long as it's for a window in the current application. Event provides a basic description of the event, like<Shift-Button-2>or<<Paste>>. if Window is empty, the whole screen is meant, and coordinates are relative to the screen. Event may have any of the forms allowed for thesequenceargument of thebindcommand, except that it has to consist of a single event pattern β not a sequence, bestie, one (1) pattern only. option-value pairs can specify additional attributes of the event, like thexandymouse position β see EVENT FIELDS below for the full tea π«. if the-whenoption isn't specified, the event is processed immediately: all of the handlers for the event will complete before theevent generatecommand returns. if-whenis specified, then it decides when the event gets processed. certain events β key events, looking at you π β require that the window has focus to receive the event properly.event info ?<<virtual>>?β the gossip form. returns information about virtual events. if the<<virtual>>argument is omitted, the return value is a list of all the virtual events currently defined. if<<virtual>>is specified, the return value is a list whose elements are the physical event sequences currently defined for that given virtual event; and if the virtual event isn't defined, you get an empty string back (ghosted π).
β οΈ note that virtual events that are not bound to physical event sequences are not returned by event info. literally they will not show up, iykyk.
okay that's the core of it and we're barely warmed up β the rest of this page is coming, don't you dare close the tab π
β¨ EVENT FIELDS β¨
okay bestie, these are the options supported for the event generate command, and they line up exactly with the % expansions youβre allowed to use in binding scripts for bind. cute, right? π
-above windowβ sets theabovefield for the event.windowcan be a window path name or an integer window id. Valid forConfigureevents. Corresponds to the%asubstitution for binding scripts. πͺ-borderwidth sizeβsizehas to be a screen distance, and it sets theborder_widthfield for the event. Valid forConfigureevents. Corresponds to the%Bsubstitution for binding scripts. β¨-button numberβnumberhas to be an integer, and it sets thedetailfield for aButtonorButtonReleaseevent, overriding any button number provided in the base event argument. Corresponds to the%bsubstitution for binding scripts. π±οΈ-count numberβnumberhas to be an integer, and it sets thecountfield for the event. Valid forExposeevents. Corresponds to the%csubstitution for binding scripts. π’-data stringβstringcan be any value, and it sets theuser_datafield for the event. Only valid for virtual events. Corresponds to the%dsubstitution for virtual events in binding scripts. πΎ-delta numberβnumberhas to be an integer, and it sets thedeltafield for theMouseWheelevent. The delta refers to the direction and magnitude the mouse wheel was rotated. Note that the value is not a screen distance β itβs units of motion in the mouse wheel. Typically these values are multiples of120. For example,120should scroll the text widget up4lines and-240would scroll the text widget down8lines. Of course, other widgets may define different behaviors for mouse wheel motion. This field corresponds to the%Dsubstitution for binding scripts. π‘-detail detailβdetailsets thedetailfield for the event and must be one of the following:NotifyAncestor,NotifyNonlinearVirtual,NotifyDetailNone,NotifyPointer,NotifyInferior,NotifyPointerRoot,NotifyNonlinear,NotifyVirtual. Valid forEnter,Leave,FocusInandFocusOutevents. Corresponds to the%dsubstitution for binding scripts. π-focus booleanβbooleanhas to be a boolean value, and it sets thefocusfield for the event. Valid forEnterandLeaveevents. Corresponds to the%fsubstitution for binding scripts. π―-height sizeβsizehas to be a screen distance, and it sets theheightfield for the event. Valid forConfigureevents. Corresponds to the%hsubstitution for binding scripts. π-keycode numberβnumberhas to be an integer, and it sets thekeycodefield for the event. Valid forKeyandKeyReleaseevents. Corresponds to the%ksubstitution for binding scripts. β¨οΈ-keysym nameβnamehas to be the name of a valid keysym, such asg,space, orReturn; its corresponding keycode value is used as thekeycodefield for the event, overriding anydetailspecified in the base event argument. Valid forKeyandKeyReleaseevents. Corresponds to the%Ksubstitution for binding scripts. π«Ά-mode notifyβnotifysets themodefield for the event and must be one ofNotifyNormal,NotifyGrab,NotifyUngrab, orNotifyWhileGrabbed. Valid forEnter,Leave,FocusIn, andFocusOutevents. Corresponds to the%msubstitution for binding scripts. π-override booleanβbooleanhas to be a boolean value, and it sets theoverride_redirectfield for the event. Valid forMap,Reparent, andConfigureevents. Corresponds to the%osubstitution for binding scripts. πͺ-place whereβwheresets theplacefield for the event; it must be eitherPlaceOnToporPlaceOnBottom. Valid forCirculateevents. Corresponds to the%psubstitution for binding scripts. ποΈ-root windowβwindowhas to be either a window path name or an integer window identifier, and it sets therootfield for the event. Valid forKey,KeyRelease,Button,ButtonRelease,Enter,Leave, andMotionevents. Corresponds to the%Rsubstitution for binding scripts. π³-rootx coordβcoordhas to be a screen distance, and it sets thex_rootfield for the event. Valid forKey,KeyRelease,Button,ButtonRelease,Enter,Leave, andMotionevents. Corresponds to the%Xsubstitution for binding scripts. π-rooty coordβcoordhas to be a screen distance, and it sets they_rootfield for the event. Valid forKey,KeyRelease,Button,ButtonRelease,Enter,Leave, andMotionevents. Corresponds to the%Ysubstitution for binding scripts. π-sendevent booleanβbooleanhas to be a boolean value, and it sets thesend_eventfield for the event. Valid for all events. Corresponds to the%Esubstitution for binding scripts. π¨-serial numberβnumberhas to be an integer, and it sets theserialfield for the event. Valid for all events. Corresponds to the%#substitution for binding scripts. π’-state stateβstatesets thestatefield for the event. ForKey,KeyRelease,Buttons,ButtonRelease,Enter,Leave, andMotionevents it must be an integer value. ForVisibilityevents it must be one ofVisibilityUnobscured,VisibilityPartiallyObscured, orVisibilityFullyObscured. This option overrides any modifiers such asMetaorControlspecified in the base event. Corresponds to the%ssubstitution for binding scripts. π§-subwindow windowβwindowsets thesubwindowfield for the event, either as a path name for a Tk widget or as an integer window identifier. Valid forKey,KeyRelease,Button,ButtonRelease,Enter,Leave, andMotionevents. Similar to%Ssubstitution for binding scripts. πͺ-time integerβintegerhas to be an integer value, and it sets thetimefield for the event. Additionally, the special valuecurrentis allowed; this value will be substituted by the current event time. Valid forKey,KeyRelease,Button,ButtonRelease,Enter,Leave,Motion, andPropertyevents. Corresponds to the%tsubstitution for binding scripts. β°-warp booleanβbooleanhas to be a boolean value, and it specifies whether the screen pointer should be warped as well. Valid forKey,KeyRelease,Button,ButtonRelease, andMotionevents. The pointer will only warp to a window if it is mapped. π-width sizeβsizehas to be a screen distance, and it sets thewidthfield for the event. Valid forConfigureevents. Corresponds to the%wsubstitution for binding scripts. π-when whenβwhendetermines when the event will be processed; it must have one of the following values:nowβ process the event immediately, before the command returns. This also happens if the-whenoption is omitted. β‘tailβ place the event on Tclβs event queue behind any events already queued for this application. πΆββοΈheadβ place the event at the front of Tclβs event queue, so that it will be handled before any other events already queued. πmarkβ place the event at the front of Tclβs event queue but behind any other events already queued with-when mark. This option is useful when generating a series of events that should be processed in order but at the front of the queue. π
-x coordβcoordhas to be a screen distance, and it sets thexfield for the event. Valid forKey,KeyRelease,Button,ButtonRelease,Motion,Enter,Leave,Expose,Configure,Gravity, andReparentevents. Corresponds to the%xsubstitution for binding scripts. IfWindowis empty the coordinate is relative to the screen, and this option corresponds to the%Xsubstitution for binding scripts. β‘οΈ-y coordβcoordhas to be a screen distance, and it sets theyfield for the event. Valid forKey,KeyRelease,Button,ButtonRelease,Motion,Enter,Leave,Expose,Configure,Gravity, andReparentevents. Corresponds to the%ysubstitution for binding scripts. IfWindowis empty the coordinate is relative to the screen, and this option corresponds to the%Ysubstitution for binding scripts. β¬οΈ
Any options that are not specified when generating an event are filled with the value 0, except for serial, which is filled with the next X event serial number. and thatβs the default vibe π
β¨ PREDEFINED VIRTUAL EVENTS β¨
ok so Tk comes with a whole pre-loaded stash of virtual events, no cap π Here's the first batch β these exist purely for notification vibes:
<<AltUnderlined>>β this one gets sent to a widget to let it know that the letter it underlined (you know, the accelerator indicator it set up with the-underlineoption) got pressed together with the Alt key. The usual slay response? Either focus into the widget (or some related widget), or just invoke the widget. periodt.<<Invoke>>β you can send this to certain widgets (likebutton,listbox,menu) as a whole alternative to<space>. iconic behavior tbh.<<ListboxSelect>>β fires at a listbox the moment the set of selected item(s) inside it gets updated. π¦<<MenuSelect>>β sent to a menu when the currently selected item in that menu changes. It's literally built for context-sensitive help systems, iykyk.<<Modified>>β sent to a text widget when the contents of the widget are changed. bestie's little "something moved" ping π<<Selection>>β sent to a text widget when the selection in the widget is changed.<<ThemeChanged>>β sent to all widgets when the ttk theme changed. The ttk widgets literally listen for this event and redisplay themselves when it fires. The legacy widgets? They ignore this event entirely π<<TkWorldChanged>>β this event is sent to all widgets when a font is changed, for example by the use of[font configure]. Theuser_datafield (%d) will have the value"FontChanged". For other system wide changes, this event gets sent to all widgets, and theuser_datafield will indicate the cause of the change. NOTE: all tk and ttk widgets already handle this event internally β¨<<TraverseIn>>β sent to a widget when the focus enters the widget because of a user-driven βtab to widgetβ action. main character entrance energy π<<TraverseOut>>β sent to a widget when the focus leaves the widget because of a user-driven βtab to widgetβ action. bye bestie π<<UndoStack>>β sent to a text widget when its undo stack or redo stack becomes empty or unempty. yes, "unempty" is a word now, we don't make the rules π<<WidgetViewSync>>β sent to a text widget when its internal data become obsolete, and again when those internal data are back in sync with the widget view. The detail field (the%dsubstitution) is eithertrue(widget is in sync) orfalse(it is not). vibe check passed or failed, basically π
ok and then there's a whole second family of virtual events, and these ones exist for the purpose of unifying bindings across multiple platforms π«Ά Users expect them to behave in the following way:
<<Clear>>β delete the currently selected widget contents. yeet it ποΈ<<Copy>>β copy the currently selected widget contents to the clipboard.<<Cut>>β move the currently selected widget contents to the clipboard.<<LineEnd>>β move to the end of the line in the current widget while deselecting any selected contents.<<LineStart>>β move to the start of the line in the current widget while deselecting any selected contents.<<NextChar>>β move to the next item (i.e., visible character) in the current widget while deselecting any selected contents.<<NextLine>>β move to the next line in the current widget while deselecting any selected contents.<<NextPara>>β move to the next paragraph in the current widget while deselecting any selected contents.<<NextWord>>β move to the next group of items (i.e., visible word) in the current widget while deselecting any selected contents.<<Paste>>β replace the currently selected widget contents with the contents of the clipboard. the classic π<<PasteSelection>>β insert the contents of the selection at the mouse location. (This event has meaningful%xand%ysubstitutions β so yeah, it actually knows where your cursor is π±οΈ)<<PrevChar>>β move to the previous item (i.e., visible character) in the current widget while deselecting any selected contents.<<PrevLine>>β move to the previous line in the current widget while deselecting any selected contents.<<PrevPara>>β move to the previous paragraph in the current widget while deselecting any selected contents.<<PrevWindow>>β traverse to the previous window.<<PrevWord>>β move to the previous group of items (i.e., visible word) in the current widget while deselecting any selected contents.<<Redo>>β redo one undone action. the comeback tour π₯<<SelectAll>>β set the range of selected contents to the complete widget. ctrl-a supremacy.<<SelectLineEnd>>β move to the end of the line in the current widget while extending the range of selected contents.<<SelectLineStart>>β move to the start of the line in the current widget while extending the range of selected contents.<<SelectNextChar>>β move to the next item (i.e., visible character) in the current widget while extending the range of selected contents.<<SelectNextLine>>β move to the next line in the current widget while extending the range of selected contents.<<SelectNextPara>>β move to the next paragraph in the current widget while extending the range of selected contents.<<SelectNextWord>>β move to the next group of items (i.e., visible word) in the current widget while extending the range of selected contents.<<SelectNone>>β reset the range of selected contents to be empty. de-select, un-highlight, done π§<<SelectPrevChar>>β move to the previous item (i.e., visible character) in the current widget while extending the range of selected contents.<<SelectPrevLine>>β move to the previous line in the current widget while extending the range of selected contents.<<SelectPrevPara>>β move to the previous paragraph in the current widget while extending the range of selected contents.<<SelectPrevWord>>β move to the previous group of items (i.e., visible word) in the current widget while extending the range of selected contents.<<ToggleSelection>>β toggle the selection. flip it and reverse it β<<Undo>>β undo the last action. the single most important keybind in existence, ngl π
πΈ EXAMPLES πΈ
MAPPING KEYS TO VIRTUAL EVENTS
ok so for a virtual event binding to actually trigger, two things gotta happen. First: the virtual event must be defined with the event add command. Second: a binding must be created for that virtual event with the bind command. Both. not one, both. π
Consider the following virtual event definitions:
event add <<Paste>> <Control-y>
event add <<Paste>> <Button-2>
event add <<Save>> <Control-X><Control-S>
event add <<Save>> <Shift-F12>
if {[tk windowingsystem] eq "aqua"} {
event add <<Save>> <Command-s>
}
And in the bind command, a virtual event can be bound like any other builtin event type, like this:
bind Entry <<Paste>> {%W insert [selection get]}
The double angle brackets are how you specify that a virtual event is being bound β << >>, that's the giveaway π If the user types Control-y or presses button 2, or if a <<Paste>> virtual event is synthesized with event generate, then the <<Paste>> binding will be invoked. slay.
Now here's a little plot twist π«Ά If a virtual binding has the exact same sequence as a separate physical binding, then the physical binding will take precedence. Consider this:
event add <<Paste>> <Control-y> <Meta-Control-y>
bind Entry <Control-y> {puts Control-y}
bind Entry <<Paste>> {puts Paste}
When the user types Control-y, the <Control-y> binding will be invoked β because a physical event is considered more specific than a virtual event, all other things being equal. BUT when the user types Meta-Control-y, the <<Paste>> binding will be invoked, because the Meta modifier in the physical pattern associated with the virtual binding is more specific than the <Control-y> sequence for the physical event. see how that flips? literal main character energy from the Meta modifier π
Also very important: bindings on a virtual event may be created before the virtual event exists. Like, the virtual event never actually needs to be defined β for instance, on platforms where that specific virtual event would be meaningless or ungeneratable. it's giving "manifesting" tbh β¨
And when a definition of a virtual event changes at run time, all windows will respond immediately to the new definition. Starting from the preceding example, if this code is executed:
bind Entry <Control-y> {}
event add <<Paste>> <F6>
then the behavior will change in two ways. First, the shadowed <<Paste>> binding will emerge β typing Control-y will no longer invoke the <Control-y> binding, but instead invoke the virtual event <<Paste>>. Second, pressing the F6 key will now also invoke the <<Paste>> binding. two-for-one glow-up π₯
MOVING THE MOUSE POINTER
Sometimes it is genuinely useful to be able to really move the mouse pointer. For example, if you have some software that's capable of demonstrating directly to the user how to use the program. To do this, you need to βwarpβ the mouse around by using event generate, like this:
for {set xy 0} {$xy < 200} {incr xy} {
event generate . <Motion> -x $xy -y $xy -warp 1
update
after 50
}
β οΈ ok but listen β it is usually considered bad style to move the mouse pointer for the user, because it removes control from them. So use this technique with caution, bestie. Also note that it is not guaranteed to function on all platforms. π«Ά
π SEE ALSO π
bind(n)β go read that one next, it's the whole other half of this story π
π KEYWORDS π
event, binding, define, handle, virtual event
and that's the whole page, you made it!! π¦β¨ this little icon came from Tk 8.3, the event(n) page, dated back in the day β go forth and bind responsibly, mwah ππΈ
π¦ where this page comes from
- alpine 3.23: tk9-doc 9.0.3-r0 Β· TCL
- alpine 3.24: tk9-doc 9.0.3-r2 Β· TCL
- fedora 43: tk 1:9.0.2-1.fc43 Β· TCL AND HPND-Pbmplus AND CC-BY-SA-3.0 AND MIT-open-group AND MIT
- fedora 43: tk 1:9.0.2-1.fc43 Β· TCL AND HPND-Pbmplus AND CC-BY-SA-3.0 AND MIT-open-group AND MIT
- fedora 44: tk 1:9.0.2-1.fc44 Β· TCL AND HPND-Pbmplus AND CC-BY-SA-3.0 AND MIT-open-group AND MIT
- fedora 44: tk 1:9.0.2-1.fc44 Β· TCL AND HPND-Pbmplus AND CC-BY-SA-3.0 AND MIT-open-group AND MIT
- nixos 26.05: tk 9.0.3
- Copyright (c) 1996 Sun Microsystems, Inc
- Copyright (c) 1998-2000 Ajuba Solutions
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms