Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
MonitorEvents.c
/* |
* MonitorEvents.c |
* EventMonitorTest |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple |
Computer, Inc. ("Apple") in consideration of your agreement to the |
following terms, and your use, installation, modification or |
redistribution of this Apple software constitutes acceptance of these |
terms. If you do not agree with these terms, please do not use, |
install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Computer, |
Inc. may be used to endorse or promote products derived from the Apple |
Software without specific prior written permission from Apple. Except |
as expressly stated in this notice, no other rights or licenses, express |
or implied, are granted by Apple herein, including but not limited to |
any patent rights that may be infringed by your derivative works or by |
other works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
Copyright © 2005 Apple Computer, Inc., All Rights Reserved |
* Created 10/28/05. |
* |
*/ |
#include "MonitorEvents.h" |
static EventHandlerRef sHandler, fHandler; |
static Boolean gApplicationActive = TRUE; |
static Boolean gProcessForegroundEvents = FALSE; |
/* |
MonitorHandler - called whenever the Event monitor target detects a registered event happens. |
determine the type of event and send a message to the system log as to the event type |
*/ |
static OSStatus MonitorHandler( EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon ) |
{ |
char* className = NULL; |
char* kindName = NULL; |
Point pt; |
UInt32 ch; |
// get the event class |
switch ( GetEventClass( inEvent ) ) |
{ |
case kEventClassKeyboard: |
className = "Keyboard"; |
// get the keyboard event type |
switch ( GetEventKind( inEvent ) ) |
{ |
case kEventRawKeyDown: |
kindName = "KeyDown"; |
GetEventParameter(inEvent, kEventParamKeyCode, |
typeUInt32, NULL, sizeof(UInt32), NULL, &ch); |
fprintf(stderr, "keycode - %d - ", (int)ch); |
break; |
case kEventRawKeyUp: |
kindName = "KeyUp"; |
GetEventParameter(inEvent, kEventParamKeyCode, |
typeUInt32, NULL, sizeof(UInt32), NULL, &ch); |
fprintf(stderr, "keycode - %d - ", (int)ch); |
break; |
case kEventRawKeyRepeat: |
kindName = "KeyRepeat"; |
GetEventParameter(inEvent, kEventParamKeyCode, |
typeUInt32, NULL, sizeof(UInt32), NULL, &ch); |
fprintf(stderr, "keycode - %d - ", (int)ch); |
break; |
case kEventRawKeyModifiersChanged: |
GetEventParameter(inEvent, kEventParamKeyModifiers, |
typeUInt32, NULL, sizeof(UInt32), NULL, &ch); |
fprintf(stderr, "0x%x - ", (unsigned int)ch); |
kindName = "ModifiersChanged"; |
break; |
default: |
break; |
} |
break; |
case kEventClassMouse: |
className = "Mouse"; |
// get the type or mouse event |
switch ( GetEventKind( inEvent ) ) |
{ |
case kEventMouseDown: |
kindName = "MouseDown"; |
break; |
case kEventMouseUp: |
kindName = "MouseUp"; |
break; |
case kEventMouseMoved: |
kindName = "MouseMoved"; |
GetEventParameter(inEvent, kEventParamMouseLocation, |
typeQDPoint, NULL, sizeof(Point), NULL, &pt); |
fprintf(stderr, "location - %d, %d - ", pt.v, pt.h); |
break; |
case kEventMouseDragged: |
kindName = "MouseDragged"; |
break; |
case kEventMouseWheelMoved: |
kindName = "MouseWheel"; |
break; |
default: |
break; |
} |
break; |
case kEventClassTablet: |
className = "Tablet"; |
// get the kind of tablet event |
switch ( GetEventKind( inEvent ) ) |
{ |
case kEventTabletPoint: |
kindName = "TabletPoint"; |
break; |
case kEventTabletProximity: |
kindName = "TabletProximity"; |
break; |
default: |
break; |
} |
break; |
default: |
break; |
} |
fprintf( stderr, "event class = %s, kind = %s\n", |
className != NULL ? className : "<unknown>", |
kindName != NULL ? kindName : "<unknown>" ); |
return noErr; |
} |
/* |
CmdHandler was originall setup to process mouse clicks in the Main Window which presents the user with |
different event types to be tracked by the process. As each item is selected/unselected a call |
to AddEventTypesToHandler/RemoveEventTypesFromHandler to process the event. |
This function has since been updated to check whether to process foreground keyboard and mouse |
events in the same way that the events are processed while the application is in the |
background. |
*/ |
static OSStatus CmdHandler( EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon ) |
{ |
HICommandExtended cmd; |
EventTypeSpec* eventList = NULL; |
OSStatus err; |
UInt32 class; |
class = GetEventClass( inEvent ); |
if (class != kEventClassCommand) |
{ |
// if this is not an EventClassCommand, then it could be a mouse or keyboard event |
// see if we should log the event. |
if ((gApplicationActive == TRUE) && (gProcessForegroundEvents == TRUE)) |
{ |
err = MonitorHandler(inCaller, inEvent, inRefcon); |
return err; |
} |
return noErr; |
} |
// log the event ID information - which button on the selection dialog did the user click on |
GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof( cmd ), NULL, &cmd ); |
fprintf(stderr, "CmdHandler called - cmd.commandID is %c%c%c%c\n", (char)(((UInt32)cmd.commandID&0xff000000)>>24), |
(char)(((UInt32)cmd.commandID&0xff0000)>>16), |
(char)(((UInt32)cmd.commandID&0xff00)>>8), |
(char)((UInt32)cmd.commandID&0xff)); |
switch ( cmd.commandID ) |
{ |
case kCmdKeyDown: |
{ |
// KeyDown radio button setting toggled |
EventTypeSpec kEvent = { kEventClassKeyboard, kEventRawKeyDown }; |
eventList = &kEvent; |
break; |
} |
case kCmdKeyUp: |
{ |
// KeyUp radio button setting toggled |
EventTypeSpec kEvent = { kEventClassKeyboard, kEventRawKeyUp }; |
eventList = &kEvent; |
break; |
} |
case kCmdKeyRepeat: |
{ |
// KeyRepeat radio button setting toggled |
EventTypeSpec kEvent = { kEventClassKeyboard, kEventRawKeyRepeat }; |
eventList = &kEvent; |
break; |
} |
case kCmdKeyModifiersChanged: |
{ |
// ModifiersChanged radio button setting toggled |
EventTypeSpec kEvent = { kEventClassKeyboard, kEventRawKeyModifiersChanged }; |
eventList = &kEvent; |
break; |
} |
case kCmdMouseDown: |
{ |
// MouseDown radio button setting toggled |
EventTypeSpec kEvent = { kEventClassMouse, kEventMouseDown }; |
eventList = &kEvent; |
break; |
} |
case kCmdMouseUp: |
{ |
// MouseUp radio button setting toggled |
EventTypeSpec kEvent = { kEventClassMouse, kEventMouseUp }; |
eventList = &kEvent; |
break; |
} |
case kCmdMouseMoved: |
{ |
// MouseMoved radio button setting toggled |
EventTypeSpec kEvent = { kEventClassMouse, kEventMouseMoved }; |
eventList = &kEvent; |
break; |
} |
case kCmdMouseDragged: |
{ |
// MouseDragged radio button setting toggled |
EventTypeSpec kEvent = { kEventClassMouse, kEventMouseDragged }; |
eventList = &kEvent; |
break; |
} |
case kCmdMouseWheel: |
{ |
// MouseWheel radio button setting toggled |
EventTypeSpec kEvent = { kEventClassMouse, kEventMouseWheelMoved }; |
eventList = &kEvent; |
break; |
} |
case kCmdTabletPoint: |
{ |
// TabletPoint radio button setting toggled |
EventTypeSpec kEvent = { kEventClassTablet, kEventTabletPoint }; |
eventList = &kEvent; |
break; |
} |
case kCmdTabletProximity: |
{ |
// TabletProximity radio button setting toggled |
EventTypeSpec kEvent = { kEventClassTablet, kEventTabletProximity }; |
eventList = &kEvent; |
break; |
} |
case kCmdForeground: |
{ |
// The "process foreground events" radio button was toggled. |
// get the current setting of the control |
eventList = NULL; |
if ( GetControlValue( cmd.source.control ) != 0 ) |
gProcessForegroundEvents = TRUE; |
else |
gProcessForegroundEvents = FALSE; |
break; |
} |
default: |
break; |
} |
if ( eventList != NULL ) |
{ |
// get the current setting of the control |
if ( GetControlValue( cmd.source.control ) != 0 ) |
{ |
OSStatus err1; |
// control was toggled on so add event type to both handler lists - the one for the |
// EventMonitor target as well as for the main event handler |
err = AddEventTypesToHandler( sHandler, 1, eventList ); |
err1 = AddEventTypesToHandler( fHandler, 1, eventList ); |
if ((err) || (err1)) |
{ |
fprintf(stderr, "error adding event type - error was %d, %d\n", (int)err, (int)err1); |
} |
else |
{ |
fprintf(stderr, "ok adding event type\n"); |
} |
} |
else |
{ |
// control was toggled off so remove event from both handler lists. |
RemoveEventTypesFromHandler( sHandler, 1, eventList ); |
RemoveEventTypesFromHandler( fHandler, 1, eventList ); |
} |
return noErr; |
} |
else |
{ |
return eventNotHandledErr; |
} |
} |
static OSStatus SuspendResumeHandler( EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon ) |
{ |
switch(GetEventKind(inEvent)) |
{ |
case kEventAppActivated: |
gApplicationActive = TRUE; |
fprintf(stderr, "Application is now frontmost\n"); |
break; |
case kEventAppDeactivated: |
gApplicationActive = FALSE; |
fprintf(stderr, "Application is now in the background\n"); |
break; |
} |
return noErr; |
} |
OSStatus InstallMyEventHandlers(void) |
{ |
EventTypeSpec kEvents[] = |
{ |
// use an event that isn't monitored just so we have a valid EventTypeSpec to install |
{ kEventClassCommand, kEventCommandUpdateStatus } |
}; |
EventTypeSpec kCmdEvents[] = |
{ |
{ kEventClassCommand, kEventCommandProcess } |
}; |
EventTypeSpec kSuspendResumeEvents[]={{kEventClassApplication,kEventAppActivated}, |
{kEventClassApplication,kEventAppDeactivated}}; |
// install an event handler to detect clicks on the main window to tell the application which |
// events to track/stop tracking |
InstallApplicationEventHandler( CmdHandler, GetEventTypeCount( kCmdEvents ), kCmdEvents, 0, &fHandler ); |
// the magic happens here with the call to GetEventMonitorTarget as described in CarbonEvents.h |
// The event monitor target is a special event target used to monitor user input events across all processes. |
// When the monitor target detects a matching event, then MonitorHandler is called. |
InstallEventHandler( GetEventMonitorTarget(), MonitorHandler, GetEventTypeCount( kEvents ), |
kEvents, 0, &sHandler ); |
// handle suspend and resume events to detect when these transitions occur so that we know when this test |
// process is in the foreground or not |
InstallApplicationEventHandler(NewEventHandlerUPP(SuspendResumeHandler), GetEventTypeCount( kSuspendResumeEvents ), |
kSuspendResumeEvents, 0, NULL); |
return noErr; |
} |
Copyright © 2005 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2005-11-09