Event Handling

This section describes how the various types of events are handled, and how the Application, Document, Window and View classes interact when handling events.

Events can be classified into three groups:

  1. Mouse events
  2. Keyboard events
  3. Menu commands

Although menu commands are not explicitly represented as Event objects, they are handled in a similar way to events.

Mouse events

There are four kinds of mouse events, mouse-down, mouse-drag, mouse-up and mouse_move.

Mouse-down and mouse-up events occur when a mouse button is pressed or released. Mouse-drag events occur when the mouse is moved with a button held down. Mouse-move events occur when the mouse is moved with no button down.

Mouse events are delivered simply by calling the correspondingly-named method, if any, of the View object with which they are associated. For example, mouse-down events are delivered by calling the mouse_down method of the view in which it occurs. If that view does not define a method with that name, the event is ignored.

Note that mouse-drag and mouse-up events are sent to the view in which the preceding mouse-down event occurred, not the one currently containing the mouse.

There is also an alternative way of receiving mouse-drag and mouse-up events, by entering a modal mouse-tracking loop in response to a mouse-down event (see Mouse Tracking).

Message delivery mechanism

Keyboard events and menu commands are handled by a general mechanism called the message delivery mechanism. A message consists of a message name and optionally a tuple of arguments. The objects which can respond to messages are subclasses of MessageHandler, and are arranged in a hierarchy which corresponds partly to the Component containment hierarchy.

Message delivery proceeds in two phases, the dispatching phase and the handling phase.

At any given moment, one of the application's windows is the target window for keboard events and menu commands. Depending on the platform, this may be the frontmost window, or the window containing the mouse pointer, or it may be determined in some other way. Within the target window, one of the components is designated as the target object, or just target. The user typically makes a component the target by clicking on it or tabbing into it. A component can also be made the target by calling its become_target method.

If no component has been selected as the target within a window, the target defaults to the window itself. If the application has no windows (possible on some platforms), the Application is the target.

The dispatching phase consists of locating the target object and passing the message to it. The handling phase is then entered by calling the handle method of the target. If the target has a method called xxx, where xxx is the name of the message, it is called with the message arguments. Otherwise, the message is passed to the handle method of the object's next handler. In the case of a Component, the next handler is the component's container.

When the message reaches a Window object, it passes to the Document object which owns the Window, and then to the Application object. If the Window is not owned by a Document, the message is passed directly to the Application.

Keyboard events

Keyboard events may be classified into key-down, key-up and auto-key events.

Key-down events are processed by dispatching a message named key_down, with the event as its argument, to the current target.

Key-up events are not supported by all platforms. Where they are supported, they are handled by dispatching a key_up message to the current target.

An auto-key event is a key-down event generated by an auto-repeating key rather than a physical keystroke, and is also handled by dispatching a key_down message. Not all platforms allow auto-key events to be distinguished from key-down events; on platforms which do, they are distinguished by the auto attribute of the event object being set to true.

Menu commands

The binding between a menu item and the action it invokes is through an internal command name associated with the menu item. This allows menu items to be rearranged and their text altered without affecting the code of objects which handle the commands. Furthermore, the method to invoke in response to a menu command is located by sending messages along the same paths that keyboard events follow. This allows the same menu item to have different effects depending on the context in which it is used.

There are two phases to handling menu commands, the setup phase and the execution phase. Each of these phases involves sending messages up the message handler hierarchy.

The purpose of the setup phase is to set up the menus so that the appropriate subset of the commands are enabled, and any check marks or other visual indications are in an appropriate state.

Before pulling down the menu, all items in all menus of the current menubar are first disabled (and any check marks, etc. are removed). Then the setup_menus method of each object along the next-handler chain from the current target is called. In response to this, each object enables those menu commands which it knows about and are currently legal (and sets up any necessary check marks, etc.)

Then the menu is pulled down and the user allowed to make a selection. If a selection is made, a message is dispatched whose name is the command name of the selected item.

As well as a single menu item, a command name can also be associated with a group of menu items whose contents can vary at run time. Examples might be a list of font names in a Font menu, or a list of window titles in a Windows menu. Within the group, individual items are distinguished by an integer index. When an item from the list is invoked, its index is passed as a parameter of the command message.