Publishers of technology books, eBooks, and videos for creative people

Home > Articles > Apple > Operating Systems

Events and Event Handlers in OS X

The number of different types of events that can occur in a Mac environment is vast. A mouse button click on a control, a mouse button click on a menu, a window collapsing, expanding, zooming, or closing, a disc inserted into the computer, and many, many other actions cause the generation of an event. Your program won't need to watch for, or respond to, every type of event. Instead, with expert author Dan Parks Sydow, you'll define the event types for which your program should watch.
This article is excerpted from Mac OS X Programming, by Dan Parks Sydow.
Like this article? We recommend

Like this article? We recommend

The number of different types of events that can occur is vast, but your program won't need to watch for, or respond to, every type of event. Instead, you'll define the event types for which your program should watch. You'll relay this information, along with information about an application-defined routine that handles the event, to the Carbon Event Manager. The routine is one that you write for the purpose of handling a particular event. It specifies what your program should do in response to the occurrence of an event of interest. Such a routine is called an event handler. After these steps are completed, you don't have to write any additional event-handling code because now the responsibility of watching for and handling particular events falls on the Carbon Event Manager.

Event Types

To distinguish one event from another, each Carbon event has an event class and an event kind associated with it. The event class specifies the broad category, such as a mouse event, to which the event belongs. The event kind further hones in on the particular nature of the event by specifying the kind of event, such as a mouse-down event, within the class. Together, the event class and event kind are referred to as an event type.

A commonly occurring event is the mouse-down event. Such an event is generated in response to a user clicking the mouse button. A click of the mouse button results in an event that has an event class of mouse event and an event kind of mouse-down. That wording might be understandable to you, but of course, the operating system needs that information in a more "code-like" manner. Apple defines a wealth of event class and event kind constants for this purpose. For a mouse click, the pertinent constants are as follows:

KEventClassMouse = FOUR_CHAR_CODE('mous');
KEventMouseDown = 1;

Both the event class constant and the event kind constant are integers, although the event class constant is specified by a four-character value that gets translated to a 32-bit integer (by way of the FOUR_CHAR_CODE macro).

In all cases, you'll be pleased to know that you aren't responsible for knowing any of the actual four-character or integer values. You need only become familiar with some of the constants with which you'll be working. The CarbonEvents.h header file lists them all. Tables 3.1 and 3.2 introduce you to two important event classes: the mouse event class (kEventClassMouse) and the window event class (kEventClassWindow). These tables list a few (but not all) of the event kinds in those two classes.

3.1 The Mouse Event Class (kEventClassMouse) and Some of Its Event Kinds

Event Kind

Cause of Event Kind

kEventMouseDown Mouse

Mouse button clicked

kEventMouseUp

Mouse button released

kEventMouseMoved

Mouse position changed

kEventMouseDragged

Mouse dragged


3.2 The Window Event Class (kEventClassWindow) and Some of Its Event Kinds

Event Kind

Cause of Event Kind

kEventWindowActivated

Window brought to front

kEventWindowDeactivated

Window sent behind

kEventWindowDrawContent

Draw (update) window's contents

kEventWindowShown

Window became visible

kEventWindowHidden

Window became invisible

kEventWindowCollapsed

Window collapsed (minimized to Dock)

kEventWindowExpanded

Window expanded (enlarged from Dock)

kEventWindowZoomed

Window zoomed


When an event class and an event type are paired, the result specifies one and only one type of event. Such a pairing is called an event type specifier. The EventTypeSpec is a structure that represents an event type specifier:

struct EventTypeSpec
{
  UInt32 eventClass;
  UInt32 eventKind;
};

Each event type has an event class and an event kind. Some event types also have event parameters (also called event attributes). The number, and purpose, of an event's parameters depends on the event type in question. For instance, the already-discussed mouse-down event type, which has an event class of kEventClassMouse and an event kind of kEventMouseDown, has four parameters that hold further information about the mouse-down event. Table 3.3 lists these event parameters and their purposes.

3.3 The Mouse-Down Event Parameters

Parameter

Represents

kEventParamMouseLocation

Location of cursor at time of mouse click

kEventParamKeyModifiers

Modifier keys pressed at time of mouse click

kEventParamMouseButton

Mouse button clicked (for the instance of a multiple-button mouse)

kEventParamClickCount

Number of mouse clicks (such as a double-click)


The EventTypeSpec keeps track of just two pieces of information—the event class and event kind—to define an event type. A different data type, the EventRef, keeps track of this same information and event parameter information. As shown in the struct definition, the composition of an EventTypeSpec structure is documented. The same isn't true of the EventRef data type.

The EventRef is an opaque type. Apple would prefer that a programmer not know its exact makeup. Making a data type opaque assures Apple that they can alter the internals of the data type at a future date without being concerned that programmers have written code that directly accesses fields of the data type.

When working with events, you'll declare a variable of type EventTypeSpec and then fill in the two fields of that structure. You'll also make use of an EventRef variable, but you'll often enable the system to fill in that structure's fields.

Your first step in handling an event is defining the event type in which your program is interested. To do this, declare an event type specifier for the event type of interest. For the upcoming discussion of installing an event handler, consider a program that's waiting for a click a button in a window. The class of such an event is considered a command, and the event kind is the processing of that command. For this situation, the event type specifier might look like this:

EventTypeSpec  eventType;

eventType.eventClass = kEventClassCommand;
eventType.eventKind = kEventProcessCommand;

An alternate way of declaring the event specifier and assigning values to its fields would be to do the work at the time of the declaration:

EventTypeSpec  eventType = { kEventClassCommand, kEventProcessCommand };

Installing an Event Handler

One of the primary jobs of the Carbon Event Manager system software is to watch for events. When this system software encounters an event about which your program is to be notified, it passes that event on to your program. In particular, it sends the event to a routine that you've written specifically to handle this type of event. Such a routine is an event handler. You'll need to write this routine (that task is covered next), and you'll need to install this routine.

To install the event handler means to provide the Carbon Event Manager system software with an association between the event type specifier (the type of event to be handled) and the event handler (the application-defined routine that should be executed at the occurrence of an event of the specified type). Pairing an event type with an event handler routine and making the Carbon Event Manager aware of this pairing requires a call to the Carbon API routine InstallEventHandler. Here's the prototype for that function:

OSStatus InstallEventHandler( EventTargetRef    target,
               EventHandlerUPP    handlerProc,
               UInt32        numTypes,
               const EventTypeSpec* typeList,
               void*         userData,
               EventHandlerRef*   handlerRef );

The InstallEventHandler parameter list might look a little daunting, so I'll cover this routine in detail here.

A program specifies an event type to watch for, and it defines an event handler routine to handle an occurrence of such an event. When the Carbon Event Manager encounters an event of the specified type and invokes the appropriate event handler routine, it needs to know upon what object the handler should act. In other words, you need to specify the target of the event. A target is a window, menu, control, or even the application itself. The target you specify should be the object "closest" to the event. For instance, if a program is watching for events that occur in a window, the window can be considered the target. Simply telling the Carbon Event Manager that a window is to be the target is not enough, though. You need to tell the Carbon Event Manager which window is the target. In addition, you need to supply this information as an EventTargetRef variable rather than as the window reference itself.

This target information is sent to the Carbon Event Manager by way of the first InstallEventHandler parameter, which is the target. You can create an EventTargetRef value by passing the intended target to the proper target routines: GetWindowEventTarget, GetMenuEventTarget, GetControlEventTarget, or GetApplicationEventTarget. Each routine takes the one argument passed to it and generates an EventTargetRef from that argument. In the following code snippet, the target of an event handler routine is to be a window that's referenced by the WindowRef variable window, and it's assumed that this window has already been created by a call to CreateWindowFromNib. The following code would generate an EventTargetRef that then could be used as the first argument to InstallEventHandler:

WindowRef    window;
EventTargetRef target;

target = GetWindowEventTarget( window );

The second InstallEventHandler parameter is handlerProc, an EventHandlerUPP. The UPP in EventHandlerUPP stands for universal procedure pointer. In short, any time you see UPP in a variable or type name, you can expect that a pointer to a routine is involved. If the Carbon Event Manager is to invoke the event handler function, it needs to know where that function's code is in memory. The handlerProc variable holds a pointer to the event handler routine. You can generate such a pointer by calling the NewEventHandlerUPP function. Simply pass the name of the event handler routine to NewEventHandlerUPP and the function returns a pointer to that function. Assuming that the as-yet unwritten event handler routine will be called MyEventHandler, the call to NewEventHandlerUPP appears as shown in the following code. The resulting EventHandlerUPP then could be passed as the second argument to InstallEventHandler.

EventHandlerUPP 	handlerUPP;

handlerUPP = NewEventHandlerUPP( MyEventHandler );

The third InstallEventHandler parameter, which is numTypes, is the number of event types to which this one event handler can respond. Although so far the focus has been on one event type and one event handler routine, it is possible to have a single event handler that's capable of handling more than one type of event.

The next parameter is typeList—a pointer to the event type or event types that this event handler routine handles. As mentioned, an event handler can serve more than one event type. Here's where the Carbon Event Manager gets the EventTypeSpec for each event type. The typeList variable is a pointer that points to either one EventTypeSpec or to an array of EventTypeSpecs.

The userData parameter is used to pass a pointer to any information that might be of use to the event handler. The pointer is passed to the Carbon Event Manager, which in turn passes the pointer to the event handler routine each time it's called. One common use for this pointer is to use it to pass a pointer to the window in which the event took place. For the handling of some event types, it might not make sense to pass supplemental information, and in such a case, you can use a value of NULL here.

The last InstallEventHandler parameter is a pointer to an event handler reference. This is a value that the Carbon Event Manager fills in for use by your program. Your program will need to use this value only if your program will be dynamically changing the event types that make use of the event handler routine. This is a situation you won't encounter often, so expect to simply pass a value of NULL here.

Now let's gather things together and take a look at a snippet that defines one type of event and installs an event handler that's to handle events of that type. The event type is used to watch for a command (such as a mouse click on a button in a window), and the event handler routine that will handle such an event is named MyEventHandler.

WindowRef    window;
EventTypeSpec  eventType;
EventTargetRef  target;
EventHandlerUPP 	handlerUPP;

eventType.eventClass = kEventClassCommand;
eventType.eventKind = kEventProcessCommand;

target = GetWindowEventTarget( window );
handlerUPP = NewEventHandlerUPP( MyEventHandler );

InstallEventHandler( target, 
           handlerUPP ),
           1, 
           &eventType,
           (void *)window, 
           NULL );

Peachpit Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from Peachpit and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about Peachpit products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites; develop new products and services; conduct educational research; and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email ask@peachpit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by Adobe Press. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.peachpit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020