Important: The information in this document is obsolete and should not be used for new development.
Dispatching Events
A MacApp application receives numerous Toolbox events from the operating system, including mouse-up and mouse-down events, key-up and key-down events, disk events, and high-level events. The application object processes Toolbox events by calling itsHandleToolboxEvent
method, with the following results:
The
- If any enabled behavior objects are attached to the application, each in turn gets a chance to handle the event until one of the objects handles the event.
- If no behavior object handles the event, the Standard Mail Package gets a chance to handle the event (if the application object is based on the
TMailingApplication
class).- If the event still hasn't been handled, it is dispatched by the application object's
DispatchEvent
method.
DispatchEvent
method calls another application method to dispatch the event. The method it calls depends on the type of event. For example,DispatchEvent
callsHandleMouseDown
for a mouse-down event,HandleActivateEvent
for an activate event, and so on.The application dispatches events by one of four mechanisms:
These mechanisms are described in the following sections.
- Direct dispatching. The application handles the event itself or sends the event directly to the object that should handle it.
- View hierarchy dispatching. The event is passed to a view hierarchy, to be handled by a view or window in the hierarchy.
- Target chain dispatching. The event is passed to a linked chain of objects that are capable of handling events and that are likely to be interested in the current event.
- High-level (Apple) event dispatching. The application calls the
AEProcessAppleEvent
routine, which causes the Apple Event Manager to dispatch the event to an application callback routine installed by MacApp's global Apple event dispatcher object. The dispatcher object attempts to resolve the specified target object and dispatch the Apple event to it. If no object is specified by the event, it is sent to the default Apple event target object. By default, MacApp specifies the application object as the default target for Apple events.
Direct Dispatching
The application object handles disk insertion and operating system events directly.
For update and activate events, the application dispatches the event directly to the object that should handle it.
- Disk insertion event. The application's
HandleDiskEvent
method checks the event to see if a disk insertion error occurred. If an error occurred, it calls the Toolbox routineDIBadMount
to display a dialog box and let the user decide what to do.- Operating system event. The application's
HandleSystemEvent
method handles these events:
suspendResumeMessage
: For a suspend event,HandleSystemEvent
deactivates the active window, informs each window that the application is about to lose control, and informs the Clipboard manager, which writes the application's data to the desk scrap. For a resume event,HandleSystemEvent
determines which window should be the front window and activates its, informs each window that the application is being activated, and informs the Clipboard manager, which checks the desk scrap for new data.mouseMovedMessage
: If the mouse has moved outside the cursor region,HandleSystemEvent
invalidates the application's cursor region. If the mouse has moved outside the help region, it invalidates the help region.
- Update event. The
HandleUpdateEvent
method finds the window object to update and calls the window'sUpdate
method.- Activate event. The
HandleActivateEvent
method finds the window object to activate and calls the window'sActivate
method.
View Hierarchy Dispatching
The application object dispatches mouse-up and mouse-down events in a window's content area to the window's view hierarchy (described on page 207) to be handled by the window or one of its views. The event is dispatched first to the window object. If the window doesn't handle the event itself, it passes the event to its subviews. Typically the event is passed down to the most deeply nested subview that contains the mouse-up or mouse-down event and wishes to respond to it.Figure 5-2 shows how MacApp handles various mouse-down and key-down events. Dispatching of mouse-down and mouse-up events is described in the following sections. Dispatching of key-down and key-up events uses the target chain dispatching mechanism, described on page 107.
Figure 5-2 How MacApp handles mouse-down and key-down events
Mouse-Down Events
To dispatch a mouse-down event, the application object'sDispatchEvent
method calls the application'sHandleMouseDown
method. What happens next depends on the location of the mouse-down event.For a mouse-down event in the menu bar, the application's
HandleMouseDown
method calls the Toolbox routineMenuSelect
to get a user menu choice, then passes the result to the application'sMenuEvent
method. If the menu choice is from the Apple menu,MenuEvent
attempts to open the chosen item or perform the specified operation. If the menu choice is from an application menu,MenuEvent
calls theHandleMenuCommand
method of the current target object, passing the chosen menu command number. The operation ofHandleMenuCommand
is described in "Target Chain Dispatching," beginning on page 107.For a mouse-down event in a system window, the application's
HandleMouseDown
method calls the Toolbox routineSystemClick
to pass the event on to the system window.For a mouse-down event in an application window, the application's
HandleMouseDown
method calls theHandleMouseDown
method of the window where the event occurred. What happens next is determined by the location of the event.
To respond to mouse-down events that are part of drawing, selecting, and similar operations, you typically override
- Mouse-down event in the window frame. If the user presses the mouse button while the cursor is in the title bar, size box, close box, or zoom box, the window's
HandleMouseDown
method calls a window method (a method of theTWindow
class) to handle the event.- Mouse-down event in the window's content area. If the user presses the mouse button while the cursor is in the window's content area, the window's
HandleMouseDown
method callsInherited::HandleMouseDown
, which results in execution of theTView::HandleMouseDown
method.The
TView::HandleMouseDown
method contains logic to handle a complex set of possibilities: is the window active or is it in the background? does the window handle first clicks (that is, a click in the window can both select the window if it is in the background and begin an operation)? can the window initiate a drag operation, and if so, is the mouse-down event over draggable content? is the mouse-down event in fact the start of a drag (the user is holding the mouse button down, not just clicking)? Depending on the answers to these questions, the actions taken byHandleMouseDown
include the following:
- It always calls the
HandleMouseDown
method of its subviews, if any, giving each subview a chance to handle the mouse-down event in itsDoMouseCommand
method.- It may initiate a drag operation (for both active and background windows).
- It may select the window (for a background window).
- It may call the
DoMouseCommand
method of each enabled behavior attached to the view to let a behavior object handle the mouse-down event.- It may call the
DoMouseCommand
method of the view itself to handle the mouse-down event. (The default implementation ofDoMouseCommand
inTView
does nothing.)
DoMouseCommand
in a view, window, or behavior class. To respond to mouse-down events that initiate drag and drop operations, you override various view methods--see Chapter 9, "Drag and Drop," for a full description.Mouse-Up Events
To dispatch a mouse-up event, the application object'sDispatchEvent
method calls the application'sHandleMouseUp
method. As with mouse-down events, what happens next depends on the location of the mouse-up event, although there are fewer options.The
HandleMouseUp
method ignores a mouse-up event in a system window.For a mouse-up event in an application window, the application object's
HandleMouseUp
method calls theHandleMouseUp
method of the window where the event occurred. This results in execution of theTView::HandleMouseUp
method.The
TView::HandleMouseUp
method callsHandleMouseUp
recursively for each of the window's subviews. A subview can handle the event itself in itsDoMouseUp
method, or an attached behavior can handle the event in itsDoMouseUp
method. If no subview or subview behavior handles the event, each behavior attached to the window itself gets a chance to handle the event.If the event isn't handled by a subview, it may be handled by the window itself if you have overridden the window's
DoMouseUp
method. If no view or window handles the event, the application'sDispatchEvent
method callsHandleAlienEvent
to handle the event as an alien event.To respond to mouse-up events, an application typically overrides
DoMouseUp
in a view, window, or behavior class.Target Chain Dispatching
There are usually a number of objects in an application that can handle a keystroke or menu event. They include the application object, as well as any document, window, or view objects that are currently active. Each of these objects is accessible through the application object--the application has a list of documents, each document has a list of windows, each window has a list of views, and each view may have a list of subviews (including control views such as buttons).The target chain is a linked list of event-handler objects that can handle the current event. It typically extends from the frontmost visible object, an active view, all the way to the application. The object at the head of the chain is called the current target object. The current target object is pointed to by the application object's
fTarget
field, which is accessed through theGetTarget
andSetTarget
methods. For example, in a window that has multiple views that can handle keystrokes, the currently selected view is normally the target.Figure 1-5 on page 14 shows a typical target chain. The current target object is a view and the next object in the chain is the view's superview, followed by its window, its document, and the application object. The next handler for the application object is usually
NULL
.MacApp handles menu choices and keystrokes by calling a method of the current target object. The target object either handles the event or sends it to the next object in the chain. As part of the process, behavior objects attached to the target object get a chance to handle the event. The process continues until either the event is handled or the end of the target chain is reached.
Behaviors and the Target Chain
MacApp allows behaviors to handle events by wrapping each event-processing method in its own special handling method. For example, theHandleMenuCommand
method is a wrapper for theDoMenuCommand
method.
(The operation ofHandleMenuCommand
andDoMenuCommand
is described in the
next section.)MacApp sends an event to the target object by calling one of these handler methods. If the target object has no enabled behavior attached to it, the handler method calls the method of the target object (for example,
DoMenuCommand
); otherwise, it calls the same method of the first enabled behavior. If the behavior has a next enabled behavior, it passes the method call on to its next behavior; otherwise it calls the same method for its owner, the target object.In this way, any enabled behavior attached to the target object gets a chance to handle the event before the object itself. If no behavior handles the event, the target object either processes the event itself, or passes it on to the next event handler in the target chain. Figure 5-3 shows this process. Each event-handler object in the target chain may have one or more behavior objects attached to it.
Figure 5-3 Behaviors on the target chain
A behavior object can point to another behavior object with its
fNextBehavior
field, making it possible to have a linked list of behaviors attached to an event-handler object. Each behavior in the list can be enabled or disabled.
Behaviors can also handle events that are not dispatched through the target chain. For example, a mouse-down event is dispatched to the window in which it occurs or to a view within that window (page 105). If the window or view has any behavior objects attached to it, they are given the opportunity to handle the mouse-down event in their
- Note
- MacApp's use of the
HandleMenuCommand
method and other event-handling methods is designed to allow behaviors to intervene in the event-handling process. You don't normally override these handling methods.DoMouseDown
methods.Menu Commands
When a user chooses a menu command, MacApp calls theHandleMenuCommand
method of the current target object, passing a value that identifies the chosen command. Figure 5-4 shows how theHandleMenuCommand
method gives each object in the target chain a chance to handle the menu command.The
HandleMenuCommand
method dispatches the menu command as follows:
You typically handle a menu command by overriding the
- It gives each enabled behavior object attached to the current target object a chance to handle the menu command.
- If no behavior object handles the menu command,
HandleMenuCommand
calls the current target object'sDoMenuCommand
method.- In the
TEventHandler
class, theDoMenuCommand
method calls theHandleMenuCommand
method of the next event handler in the target chain, if there is one (see Figure 5-3).- If no object in the chain handles the command, the command is ignored.
DoMenuCommand
method in an application, document, window, view, or behavior class.Each event-handler object in the target chain may contain multiple definitions of
DoMenuCommand
in its class hierarchy. Suppose, for example, theTYourDocument
class is a subclass ofTFileBasedDocument
that overrides theDoMenuCommand
method. As shown in Figure 5-5, there are four versions ofDoMenuCommand
in the object's class hierarchy: one version inTYourDocument
, one inTDocument
, one inTCommandHandler
, and one inTEventHandler
.Figure 5-4 Objects in the target chain responding to a menu command
When MacApp calls
DoMenuCommand
on an instance ofTYourDocument
, theTYourDocument
version ofDoMenuCommand
checks to see if it can handle the menu command. If it can't, it callsInherited::DoMenuCommand
. If no inheritedDoMenuCommand
method handles the menu command, theDoMenuCommand
method of theTEventHandler
class passes the menu command to the next event-handler object in the target chain, if there is one, by calling the object'sHandleMenuCommand
method.Key-Down Events
To dispatch a key-down event, the application object'sDispatchEvent
method calls the application'sHandleKeyDownEvent
method.
Figure 5-5 Calling the
- If the Command key was pressed,
HandleKeyDownEvent
calls theHandleCommandKey
method of the current target object. TheHandleCommandKey
method gives each behavior object and each event-handler object in the target chain the opportunity to handle the key-down event in itsDoCommandKeyEvent
method, until an object handles the event.If a Command-key event reaches the application object in the target chain, the application attempts to map the event to an equivalent menu command. For example, Command-S is mapped to the Save menu command, which has the command constant
cSave
. MacApp's numbering scheme for menu commands is described in "MacApp's Command-Numbering System," beginning on page 131.To check for a menu equivalent, the application's
DoCommandKeyEvent
method callsMenuEvent
. The operation ofMenuEvent
is described in "Mouse-Down Events," beginning on page 105.
DoMenuCommand
method of a document object
To respond to key-down events, an application typically overrides the
- If the Command key was not pressed,
HandleKeyDownEvent
calls theHandleKeyCommand
method of the current target object. TheHandleKeyCommand
method gives each behavior object and each event-handler object in the target chain the opportunity to handle the key-down event in itsDoKeyEvent
method, until an object handles the event. If no object handles the event, it is ignored.
DoCommandKeyEvent
method or theDoKeyEvent
method in an application, document, view, window, or behavior class.For more information on handling key-down events, see Chapter 20, "Working With the Keyboard."
Receiving Key-Up Events
Because most applications don't need key-up events, your application will never see one unless you change MacApp's default behavior. MacApp uses thefWantKeyUpEvents
field of theTApplication
class to control access to key-up events. The application'sRun
method contains code to modify the system event mask based onfWantKeyUpEvents
:
if (fWantKeyUpEvents) ::SetEventMask(everyEvent); // Allows us to get key-up events too.The constructor forTApplication
sets thefWantKeyUpEvents
field toFALSE
. If you want to receive key-up events, setfWantKeyUpEvents
toTRUE
in the constructor for your application subclass.Dispatching Key-Up Events
To dispatch a key-up event, the application object'sDispatchEvent
method calls the application'sHandleKeyUpEvent
method. Since applications are rarely concerned with key-up events, MacApp's mechanism for handling these events is relatively simple. TheHandleKeyUpEvent
method calls theHandleKeyUp
method of the current target object. TheHandleKeyUp
method inTEventHandler
gives each enabled behavior object and each event-handling object in the target chain a chance to handle the key-up event in itsDoKeyUp
method, until an object handles the event. If no object handles the event, it is ignored.Several MacApp classes override the
DoKeyUp
method:
- The
TBehavior
class overridesDoKeyUp
to pass the event to the behavior's next enabled behavior. If the behavior doesn't have a next enabled behavior,TBehavior::DoKeyUp
calls theDoKeyUp
method of the behavior's owner.- The
TEventHandler
class overridesDoKeyUp
to pass the event to the next event handler in the target chain by calling the next handler'sHandleKeyUp
method.- The
TKeySelectionBehavior
class overridesDoKeyUp
to keep track of a time-out interval. (TKeySelectionBehavior
tracks user typing, and can be used with aTTextListView
object to select items in a list alphabetically by type-ahead.)- The
TMailerView
class overridesDoKeyUp
to give the mailer a chance to handle key-up events.DoKeyUp
passes the event to the mailer view'sDoMailerEvent
method.
Alien Events
An alien event is one that MacApp doesn't anticipate handling. That includes network events, driver events, null events, and any other events MacApp doesn't recognize, such as events defined by your application.The application object's
DispatchEvent
method calls the application'sHandleAlienEvent
method to handle alien events. TheHandleAlienEvent
method gives each cohandler in the application's cohandler chain a chance to handle the alien event. Cohandler chains are described in "The Cohandler Chain," beginning on page 134.Dispatching High-Level Events
For high-level events (those with identifierkHighLevelEvent
), the application object'sDispatchEvent
method calls the application'sHandleHighLevelEvent
method. TheHandleHighLevelEvent
method in turn calls the Apple Event Manager routineAEProcessAppleEvent
. MacApp uses a global Apple event dispatcher object to handle callbacks from the Apple Event Manager and to communicate with the Object Support Library to determine the object specified by the Apple event.Dispatching of Apple events is described in detail in Chapter 6, "Scripting."