10.39.4.5 Servicing Tcl and Tk events

The notion of an event in the Prolog+Tcl/Tk system is overloaded. We have already come across the following kinds of events:

It is further about to be overloaded with the notion of Tcl/Tk events. It is possible to create event handlers in Tcl/Tk for reacting to other kinds of events. We will not cover them here but describe them so that the library functions are understandable and in case the user needs these features in an advanced application.

There are the following kinds of Tcl/Tk events:

idle events

happen when the Tcl/Tk system is idle

file events

happen when input arrives on a file handle that has a file event handler attached to it

timer events

happen when a Tcl/Tk timer times out

window events

when something happens to a Tk window, such as being resized or destroyed

The problem is that in advanced Tcl/Tk applications it is possible to create event handlers for each of these kinds of event, but they are not normally serviced while in Prolog code. This can result in unresponsive behavior in the application; for example, if window events are not serviced regularly, then if the user tries to resize a Tk window, it will not resize in a timely fashion.

The solution to this is to introduce a Prolog predicate that passes control to Tk for a while so that it can process its events, tk_do_one_event/[0,1]. If an application is unresponsive because it is spending a lot of time in Prolog and is not servicing Tk events often enough, critical sections of the Prolog code can be sprinkled with calls to tk_do_one_event/[0,1] to alleviate the problem.

tk_do_one_event/[0,1] has the following forms:

tk_do_one_event
tk_do_one_event(+Options)

which passes control to Tk to handle a single event before passing control back to Prolog. The type of events handled is passed through the Options variable, a list of atoms that are event types.

The Options list can contain the following atoms:

tk_dont_wait

don’t wait for new events, process only those that are ready

tk_window_events

process window events

tk_file_events

process file events

tk_timer_events

process timer events

tk_idle_events

process Tcl_DoWhenIdle events

tk_all_events

process any event

Calling tk_do_one_event/0 is equivalent to a call to tk_do_one_event/1 with the tk_all_events and tk_dont_wait flags.

A call to either of these predicates succeeds only if an event of the appropriate type happens in the Tcl/Tk interpreter. If there are no such events, tk_do_one_event/1 will fail if the tk_dont_wait wait flag is present, as will tk_do_one_event/0, which has that flag set implicitly.

If the tk_dont_wait flag is not set, a call to tk_do_one_event/1 will block until an appropriate Tk event happens (in which case it will succeed).

It is straight forward to define a predicate that handles all Tk events and then returns:

tk_do_all_events :-
    tk_do_one_event, !,
    tk_do_all_events.
tk_do_all_events.

The predicate tk_next_event/[2,3] is similar to tk_do_one_event/[0,1] except that it processes Tk events until at least one Prolog event happens. (We came across this predicate before when discussing Prolog event queue predicates. This shows the overloading of the notion event where we have a predicate that handles both Tcl/Tk events and Prolog queue events.)

It has the following forms:

tk_next_event(+TclInterpreter, -Event)
tk_next_event(+Options, +TclInterpreter, -Event)

The Prolog event is returned in the variable Event and is the first term on the Prolog event queue associated with the interpreter TclInterpreter. (Prolog events are initiated on the Tcl side through the new Tcl command prolog_event, covered earlier; see Event Functions).



Send feedback on this subject.