event(3tk)

πŸ’– event β€” no literally, the manual page for event(3tk) ✨

(from the Tk Built-In Commands era, bestie, we love a classic)


🌸 NAME 🌸

event β€” your miscellaneous little event-facility queen: she defines virtual events and she generates events, and she does it beautifully.


πŸŽ€ SYNOPSIS πŸŽ€

event option ?arg ...?

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so the event command is literally the girl who handles all your window system event situations πŸ’… β€” like, defining virtual events, and also synthesizing events out of thin air. She's got multiple forms and which one you get depends entirely on what you pass as the first argument. The following forms are currently supported, and yes, we're going through ALL of them:


✨ event add <<virtual>> sequence ?sequence ...?

Associates the virtual event virtual with the physical event sequence(s) you hand her in the sequence arguments, so the virtual event will trigger whenever any one of those sequences happens. Gorgeous. Obsessed.

virtual can be literally any string value you want, and sequence can be any of the values that are allowed for the sequence argument of the bind command. And here's the cute part: if virtual is already defined, the new physical event sequences just add on to the existing sequences for that event. She's not replacing anything, she's expanding πŸ”₯


πŸ’œ event delete <<virtual>> ?sequence sequence ...?

Deletes each of the sequences from the ones associated with the virtual event virtual. Same deal as before β€” virtual can be any string value, and sequence can be any of the values allowed for the sequence argument to the bind command.

Any sequences that aren't currently associated with virtual? Ignored. Not her problem, she moves on πŸ™ˆ

And if you provide no sequence argument at all, then all physical event sequences get removed for virtual, which means that virtual event will not trigger anymore. Periodt. It's done. She's clocked out.


🌈 event generate window event ?option value option value ...?

This one generates a window event and arranges for it to be processed exactly as if it had come from the window system. Like, cosplay but make it events.

  • window gives the path name of the window the event will be generated for. It can also be an identifier (like the ones returned by winfo id), as long as it's for a window in the current application.
  • event gives a basic description of the event, such as <Shift-Button-2> or <<Paste>>.
  • If window is empty, the whole screen is meant, and the coordinates are then relative to the screen.

event can be any of the forms allowed for the sequence argument of the bind command β€” EXCEPT it has to be a single event pattern, not a whole sequence. One pattern only, bestie, we're not doing a whole playlist here.

option-value pairs can specify extra attributes of the event, like the x and y mouse position. (Peep EVENT FIELDS below πŸ‘€)

ok important!! If the -when option is not specified, the event gets processed immediately: all of the handlers for the event will complete before the event generate command returns. But if -when is specified, then that determines when the event is processed.

Also, certain events β€” like key events β€” require that the window has focus to receive the event properly. No focus, no keys, she can't hear you πŸ’€


🌟 event info ?<<virtual>>?

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 at all? You get an empty string back. Nothing. Silence. 🫢
heads up though: virtual events that are not bound to physical event sequences are not returned by event info. Iconic behaviour honestly, but keep it in mind.

πŸ’… EVENT FIELDS πŸ’…

Okay so listen bestie πŸ‘‘ β€” these are all the lil knobs you can twiddle when you run event generate. Each one maps directly onto a % expansion you'd use in a binding script for the bind command. Same field, same vibe, different spelling. Let's go one by one, no skipping 🫢

  • -above window β€” Window sets the above field for the event. You can hand it a window path name or an integer window id, dealer's choice ✨. Only valid for Configure events. This one's the %a substitution in your binding scripts.
  • -borderwidth size β€” Size has to be a screen distance, and it sets the border_width field. Valid for Configure events only. That's %B in binding scripts.
  • -button number β€” Number is an integer, and it sets the detail field for a Button or ButtonRelease event β€” and it overrides any button number you already provided in the base event argument, so it wins the fight πŸ’…. That's %b.
  • -count number β€” Number is an integer; it sets the count field. Valid for Expose events. %c, periodt.
  • -data string β€” String can be literally anything, it sets the user_data field. Only valid for virtual events, no cap. That's %d for virtual events in binding scripts.
  • -delta number β€” Number is an integer; it sets the delta field for the MouseWheel event. The delta is the direction and the magnitude the mouse wheel got rotated by. Heads up though: this value is not a screen distance, it's units of motion in the mouse wheel, which is such a different vibe 😭. Typically these come in multiples of 120. Like, 120 should scroll the text widget up 4 lines and -240 would scroll the text widget down 8 lines. But of course other widgets can absolutely define their own behaviors for mouse wheel motion, so don't @ me. This field = the %D substitution.
  • -detail detail β€” Detail sets the detail field, and it's gotta be one of these icons only, no substitutions:
    • NotifyAncestor
    • NotifyNonlinearVirtual
    • NotifyDetailNone
    • NotifyPointer
    • NotifyInferior
    • NotifyPointerRoot
    • NotifyNonlinear
    • NotifyVirtual

Valid for Enter, Leave, FocusIn and FocusOut events. Corresponds to %d in binding scripts.

  • -focus boolean β€” Boolean has to be an actual boolean value; it sets the focus field. Valid for Enter and Leave events. That's %f.
  • -height size β€” Size is a screen distance; it sets the height field. Valid for Configure events. %h, slay.
  • -keycode number β€” Number is an integer; it sets the keycode field. Valid for Key and KeyRelease events. %k.
  • -keysym name β€” Name has to be the name of a valid keysym, like g, space, or Return, and its corresponding keycode value gets used as the keycode field β€” which means it overrides any detail you specified in the base event argument πŸ‘€. Valid for Key and KeyRelease events. That's %K.
  • -mode notify β€” Notify sets the mode field and must be one of NotifyNormal, NotifyGrab, NotifyUngrab, or NotifyWhileGrabbed. Valid for Enter, Leave, FocusIn, and FocusOut events. Corresponds to %m.
  • -override boolean β€” Boolean has to be a boolean value; it sets the override_redirect field. Valid for Map, Reparent, and Configure events. %o.
  • -place where β€” Where sets the place field and must be either PlaceOnTop or PlaceOnBottom. Valid for Circulate events. %p.
  • -root window β€” Window is either a window path name or an integer window identifier; it sets the root field. Valid for Key, KeyRelease, Button, ButtonRelease, Enter, Leave, and Motion events. %R.
  • -rootx coord β€” Coord is a screen distance; it sets the x_root field. Valid for Key, KeyRelease, Button, ButtonRelease, Enter, Leave, and Motion events. %X.
  • -rooty coord β€” Coord is a screen distance; it sets the y_root field. Valid for Key, KeyRelease, Button, ButtonRelease, Enter, Leave, and Motion events. %Y.
  • -sendevent boolean β€” Boolean is a boolean value; it sets the send_event field. Valid for all events, every single one. %E.
  • -serial number β€” Number is an integer; it sets the serial field. Valid for all events. That's %#.
  • -state state β€” State sets the state field. For Key, KeyRelease, Buttons, ButtonRelease, Enter, Leave, and Motion events it has to be an integer value. For Visibility events though, it must be one of VisibilityUnobscured, VisibilityPartiallyObscured, or VisibilityFullyObscured. Oh and this option overrides any modifiers like Meta or Control you specified in the base event. %s.
  • -subwindow window β€” Window sets the subwindow field, either as a path name for a Tk widget or as an integer window identifier. Valid for Key, KeyRelease, Button, ButtonRelease, Enter, Leave, and Motion events. This one's similar to the %S substitution for binding scripts.
  • -time integer β€” Integer has to be an integer value; it sets the time field. Also, plot twist: the special value current is allowed, and it gets substituted by the current event time 🌈. Valid for Key, KeyRelease, Button, ButtonRelease, Enter, Leave, Motion, and Property events. Corresponds to %t.
  • -warp boolean β€” boolean has to be a boolean value; it says whether the screen pointer should be warped as well. Valid for Key, KeyRelease, Button, ButtonRelease, and Motion events. Now, Tk supports pointer warping relative to the screen's root window, and relative to a Tk window. In that second case, the pointer only warps if the window is mapped, so keep that in mind bestie πŸ’œ.
  • -width size β€” Size is a screen distance; it sets the width field. Valid for Configure events. %w.
  • -when when β€” When decides when the event actually gets processed, and it has to be one of these:
    • now β€” process the event immediately, before the command even returns. This also happens if you just omit the -when option entirely.
    • 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 it gets 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 one's iconic when you're generating a whole series of events that should be processed in order but at the front of the queue.
  • -x coord β€” Coord is a screen distance; it sets the x field. Valid for Key, KeyRelease, Button, ButtonRelease, Motion, Enter, Leave, Expose, Configure, Gravity, and Reparent events. Corresponds to %x for binding scripts. Little extra detail πŸŽ€: if Window is empty the coordinate is relative to the screen, and then this option corresponds to the %X substitution instead.
  • -y coord β€” Coord is a screen distance; it sets the y field. Valid for Key, KeyRelease, Button, ButtonRelease, Motion, Enter, Leave, Expose, Configure, Gravity, and Reparent events. Corresponds to %y for binding scripts. And again, if Window is empty the coordinate is relative to the screen, and this option corresponds to the %Y substitution.
Okay so here's the tea: any options you don't specify when generating an event get filled with the value 0. Every single one... except serial, which gets filled with the next X event serial number. ✨

✨ PREDEFINED VIRTUAL EVENTS ✨

ok so Tk comes with a whole built-in set of virtual events, bestie, you don't even have to make them yourself πŸ’… Two flavors, and they do different jobs.

First up, the ones Tk defines for the purposes of notification β€” these are the "hey something happened, go look" events:

  • <<AltUnderlined>> β€” this one gets sent to a widget to let it know that the letter it underlined with the -underline option (you know, the little accelerator indicator) got pressed together with the Alt key. What you're supposed to do with it is either focus into the widget (or some related widget) or just invoke the widget. Two options, choose your fighter ✨
  • <<Invoke>> β€” this can be sent to some widgets (like button, listbox, menu) as an alternative to <space>. It's giving "press the thing without pressing the spacebar" πŸŽ€
  • <<ListboxSelect>> β€” sent to a listbox when the set of selected item(s) in that listbox gets updated. The selection changed, she's telling you πŸ“£
  • <<MenuSelect>> β€” sent to a menu when the currently selected item in the menu changes. It's literally intended for use with context-sensitive help systems, iykyk πŸ’–
  • <<Modified>> β€” sent to a text widget when the contents of the widget are changed.
  • <<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 are listening for this one and they redisplay themselves when it fires. The legacy widgets? They just ignore it entirely, no thoughts head empty πŸ’€
  • <<TkWorldChanged>> β€” sent to all widgets when a font is changed, for example by using [font configure]. The user_data field (%d) will have the value "FontChanged". For other system wide changes, this event gets sent to all widgets, and the user_data field will indicate the cause of the change. NOTE: all tk and ttk widgets already handle this event internally. so like, you don't have to do anything, but now you know 🫢
  • <<TraverseIn>> β€” sent to a widget when the focus enters the widget because of a user-driven "tab to widget" action.
  • <<TraverseOut>> β€” sent to a widget when the focus leaves the widget because of a user-driven "tab to widget" action.
  • <<UndoStack>> β€” sent to a text widget when its undo stack or redo stack becomes empty or unempty. (yes, "unempty" is a word here, 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 %d substitution) is either true (when the widget is in sync) or false (when it is not).

and then there's the second group 🌈 Tk defines these following virtual events for the purposes of unifying bindings across multiple platforms. Users expect them to behave in the following way, so here's the whole roster:

  • <<Clear>> β€” delete the currently selected widget contents.
  • <<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.
  • <<PasteSelection>> β€” insert the contents of the selection at the mouse location. (this event has meaningful %x and %y substitutions, so you actually get coordinates 🌸)
  • <<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.
  • <<SelectAll>> β€” set the range of selected contents to the complete widget.
  • <<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.
  • <<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.
  • <<Undo>> β€” undo the last action.

ok that was a lot but you survived it, so proud of you genuinely πŸ₯ΉπŸ’–


🌟 EXAMPLES 🌟

πŸŽ€ MAPPING KEYS TO VIRTUAL EVENTS πŸŽ€

so for a virtual event binding to actually trigger, two things have to happen, and neither is optional:

  1. the virtual event has to be defined with the event add command
  2. a binding has to be created for that virtual event with the bind command

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>
}

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 tell πŸ‘€ So 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.

but here's the tea 🍡 If a virtual binding has the exact same sequence as a separate physical binding, then the physical binding takes precedence. Consider the following example:

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 gets invoked, because a physical event is considered more specific than a virtual event β€” all other things being equal. However, when the user types Meta-Control-y, the <<Paste>> binding gets 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. it's giving specificity war and the modifiers are winning πŸ’…

Bindings on a virtual event may be created before the virtual event exists. In fact, the virtual event never actually needs to be defined at all β€” for instance, on platforms where that specific virtual event would be meaningless or ungeneratable. so go ahead and bind that imaginary event, she's valid ✨

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 the following code is executed:

bind Entry <Control-y> {}
event add <<Paste>> <F6>

the behavior will change in two ways:

  1. 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>>.
  2. Second, pressing the F6 key will now also invoke the <<Paste>> binding.

ok that's genuinely iconic behavior, she reinvented herself 🌈

πŸ¦‹ MOVING THE MOUSE POINTER πŸ¦‹

Sometimes it is useful to be able to really move the mouse pointer. Like, 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
}
Note that it is usually considered bad style to move the mouse pointer for the user, because it removes control from them. Therefore this technique should be used with caution. Also note that it is not guaranteed to function on all platforms. πŸ™ˆ

so yeah, moving someone's cursor is a little rude, do it at your own risk bestie 😭


πŸ‘€ SEE ALSO πŸ‘€


πŸ”‘ KEYWORDS πŸ”‘

event, binding, define, handle, virtual event


that's the whole page bb, you made it to the end πŸ₯³πŸ’œ this was the Tk 8.3 edition of event(3tk) β€” go forth and bind things, you absolute main character, periodt βœ¨πŸ‘‘πŸ’–

πŸ“¦ where this page comes from
  • ubuntu stonking: tk9.0-doc 9.0.4-1
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms