text: //
  //  GTMCarbonEvent.h
  //
  //  Copyright 2006-2008 Google Inc.
  //
  //  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  //  use this file except in compliance with the License.  You may obtain a copy
  //  of the License at
  // 
  //  http://www.apache.org/licenses/LICENSE-2.0
  // 
  //  Unless required by applicable law or agreed to in writing, software
  //  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  //  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
  //  License for the specific language governing permissions and limitations under
  //  the License.
  //
  
  #import <Foundation/Foundation.h>
  #import <Carbon/Carbon.h>
  
  #import "GTMDefines.h"
  
  @class GTMCarbonEventHandler;
  
  // Objective C wrapper for a Carbon Event
  @interface GTMCarbonEvent : NSObject <NSCopying> {
   @private
    EventRef event_;  //Event we are wrapping. STRONG
  }
  
  
  //  Create an event of class |inClass| and kind |inKind|
  //
  //  Returns:
  //    Autoreleased GTMCarbonEvent
  //
  + (id)eventWithClass:(UInt32)inClass kind:(UInt32)kind;
  
  //  Create an event based on |event|. Retains |event|.
  //
  //  Returns:
  //    Autoreleased GTMCarbonEvent
  //
  + (id)eventWithEvent:(EventRef)event;
  
  //  Create an event based on the event currently being handled.
  //
  //  Returns:
  //    Autoreleased GTMCarbonEvent
  //
  + (id)currentEvent;
  
  //  Create an event of class |inClass| and kind |inKind|
  //
  //  Returns:
  //    GTMCarbonEvent
  //
  - (id)initWithClass:(UInt32)inClass kind:(UInt32)kind;
  
  //  Create an event based on |event|. Retains |event|.
  //
  //  Returns:
  //    GTMCarbonEvent
  //
  - (id)initWithEvent:(EventRef)event;
  
  //  Get the event's class.
  //
  //  Returns:
  //    event class
  //
  - (UInt32)eventClass;
  
  //  Get the event's kind.
  //
  //  Returns:
  //    event kind
  //
  - (UInt32)eventKind;
  
  //  Set the event's time.
  //
  //  Arguments:
  //    time - the time you want associated with the event
  //
  - (void)setTime:(EventTime)eventTime;
  
  //  Get the event's time.
  //
  //  Returns:
  //    the time associated with the event
  //
  - (EventTime)time;
  
  //  Get the event's eventref for passing to other carbon functions.
  //
  //  Returns:
  //    the event ref associated with the event
  //
  - (EventRef)event;
  
  //  Sets (or adds) a parameter to an event. Try not to use this function
  //  directly. Look at the PARAM_TEMPLATE_DECL/DEFN macros below.
  //
  //  Arguments:
  //    name - the parameter name.
  //    type - the parameter type.
  //    size - the size of the data that |data| points to.
  //    data - pointer to the data you want to set the parameter to.
  //
  - (void)setParameterNamed:(EventParamName)name 
                       type:(EventParamType)type 
                       size:(ByteCount)size 
                       data:(const void *)data;
  
  
  //  Gets a parameter from an event. Try not to use this function
  //  directly. Look at the PARAM_TEMPLATE_DECL/DEFN macros below.
  //
  //  Arguments:
  //    name - the parameter name.
  //    type - the parameter type.
  //    size - the size of the data that |data| points to.
  //    data - pointer to the buffer that you want to fill with your data.
  //
  //  Returns:
  //    YES is parameter is retrieved successfully. NO if parameter doesn't exist.
  //
  - (BOOL)getParameterNamed:(EventParamName)name 
                       type:(EventParamType)type 
                       size:(ByteCount)size 
                       data:(void *)data;
  
  //  Gets a the size of a parameter from an event. 
  //
  //  Arguments:
  //    name - the parameter name.
  //    type - the parameter type.
  //
  //  Returns:
  //    The size of the buffer required to hold the parameter. 0 if parameter
  //    doesn't exist.
  //
  - (ByteCount)sizeOfParameterNamed:(EventParamName)name
                               type:(EventParamType)type;
  
  //  Sends event to an event target with options
  //
  //  Arguments:
  //    target - target to send event to.
  //    options - options to send event. See SendEventToEventTargetWithOptions
  //              for details.
  //
  //  Returns:
  //    OSStatus value.
  //
  - (OSStatus)sendToTarget:(GTMCarbonEventHandler *)target 
                   options:(OptionBits)options;
  
  //  Post event to an event queue.
  //
  //  Arguments:
  //    queue - queue to post it to.
  //    priority - priority to post it with
  //
  //  Returns:
  //    OSStatus value.
  //
  - (OSStatus)postToQueue:(EventQueueRef)queue priority:(EventPriority)priority;
  
  //  Post event to current queue with standard priority.
  //
  - (void)postToCurrentQueue;
  
  //  Post event to main queue with standard priority.
  //
  - (void)postToMainQueue;
  
  @end
  
  // Macros for defining simple set/get parameter methods for GTMCarbonEvent. See
  // the category GTMCarbonEvent (GTMCarbonEventGettersAndSetters) for an example
  // of their use. GTM_PARAM_TEMPLATE_DECL2/DEFN2 is for the case where the
  // parameter name is different than the parameter type (rare, but it does
  // occur...e.g. for a Rect, the name is typeQDRectangle, and the type is Rect,
  // so it would be GTM_PARAM_TEMPLATE_DECL2(QDRectangle, Rect) ). In most cases
  // you will just use GTM_PARAM_TEMPLATE_DECL/DEFN.
  #define GTM_PARAM_TEMPLATE_DECL2(paramName, paramType) \
  - (void)set##paramName##ParameterNamed:(EventParamName)name data:(paramType *)data; \
  - (BOOL)get##paramName##ParameterNamed:(EventParamName)name data:(paramType *)data;
  
  #define GTM_PARAM_TEMPLATE_DEFN2(paramName, paramType) \
  - (void)set##paramName##ParameterNamed:(EventParamName)name data:(paramType *)data { \
  [self setParameterNamed:name type:type##paramName size:sizeof(paramType) data:data]; \
  } \
  - (BOOL)get##paramName##ParameterNamed:(EventParamName)name data:(paramType *)data { \
  return [self getParameterNamed:name type:type##paramName size:sizeof(paramType) data:data]; \
  }
  
  #define GTM_PARAM_TEMPLATE_DECL(paramType) GTM_PARAM_TEMPLATE_DECL2(paramType, paramType)
  #define GTM_PARAM_TEMPLATE_DEFN(paramType) GTM_PARAM_TEMPLATE_DEFN2(paramType, paramType)
  
  
  // Category defining some basic types that we want to be able to easily set and
  // get from GTMCarbonEvents
  @interface GTMCarbonEvent (GTMCarbonEventGettersAndSetters)
  GTM_PARAM_TEMPLATE_DECL(UInt32)
  GTM_PARAM_TEMPLATE_DECL(EventHotKeyID)
  @end
  
  //  Utility function for converting between modifier types
  //  Arguments:
  //    inCocoaModifiers - keyboard modifiers in carbon form 
  //                       (NSCommandKeyMask etc)
  //  Returns:
  //    Carbon modifiers equivalent to |inCocoaModifiers| (cmdKey etc)
  GTM_EXTERN UInt32 GTMCocoaToCarbonKeyModifiers(NSUInteger inCocoaModifiers);
  
  // Utility function for converting between modifier types
  //  Arguments:
  //    inCarbonModifiers - keyboard modifiers in carbon form (cmdKey etc)
  //  Returns:
  //    cocoa modifiers equivalent to |inCocoaModifiers| (NSCommandKeyMask etc)
  GTM_EXTERN NSUInteger GTMCarbonToCocoaKeyModifiers(UInt32 inCarbonModifiers);
  
  // An "abstract" superclass for objects that handle events such as 
  // menus, HIObjects, etc. 
  //
  // Subclasses are expected to override the eventTarget and
  // handleEvent:handler: methods to customize them.
  @interface GTMCarbonEventHandler : NSObject {
   @private
    // handler we are wrapping  
    // lazily created in the eventHandler method
    EventHandlerRef eventHandler_;  
    __weak id delegate_;  // Our delegate
    // Does our delegate respond to the gtm_eventHandler:receivedEvent:handler:
    // selector? Cached for performance reasons.
    BOOL delegateRespondsToHandleEvent_;  
  }
  
  // Registers the event handler to listen for |events|.
  //
  // Arguments:
  //   events - an array of EventTypeSpec. The events to register for.
  //   count - the number of EventTypeSpecs in events.
  //
  - (void)registerForEvents:(const EventTypeSpec *)events count:(size_t)count;
  
  // Causes the event handler to stop listening for |events|.
  //
  // Arguments:
  //   events - an array of EventTypeSpec. The events to register for.
  //   count - the number of EventTypeSpecs in events.
  //
  - (void)unregisterForEvents:(const EventTypeSpec *)events count:(size_t)count;
  
  // To be overridden by subclasses to respond to events. 
  //
  // All subclasses should call [super handleEvent:handler:] if they
  // don't handle the event themselves.
  //
  // Arguments:
  //   event - the event to be handled
  //   handler - the call ref in case you want to call CallNextEventHandler
  //             in your method
  // Returns:
  //   OSStatus - usually either noErr or eventNotHandledErr
  //
  - (OSStatus)handleEvent:(GTMCarbonEvent *)event 
                  handler:(EventHandlerCallRef)handler;
  
  // To be overridden by subclasses to return the event target for the class.
  // GTMCarbonEventHandler's implementation returns NULL.
  //
  // Returns:
  //   The event target ref.
  //
  - (EventTargetRef)eventTarget;
  
  // Gets the underlying EventHandlerRef for that this class wraps.
  //
  // Returns:
  //   The EventHandlerRef this class wraps.
  //
  - (EventHandlerRef)eventHandler;
  
  // Gets the delegate for the handler
  //
  // Returns:
  //   the delegate
  - (id)delegate;
  
  // Sets the delegate for the handler
  //
  // Arguments:
  //   delegate - the delegate to set to
  - (void)setDelegate:(id)delegate;
  
  @end
  
  // Category for methods that a delegate of GTMCarbonEventHandlerDelegate may 
  // want to implement.
  @interface NSObject (GTMCarbonEventHandlerDelegate) 
  
  // If a delegate implements this method it gets called before every event
  // that the handler gets sent. If it returns anything but eventNotHandledErr, 
  // the handlers handlerEvent:handler: method will not be called, and
  // the return value returned by the delegate will be returned back to the
  // carbon event dispatch system. This allows you to override any method
  // that a handler may implement.
  //
  // Arguments:
  //  delegate - the delegate to set to
  //
  - (OSStatus)gtm_eventHandler:(GTMCarbonEventHandler *)sender 
                 receivedEvent:(GTMCarbonEvent *)event 
                       handler:(EventHandlerCallRef)handler;
  
  @end
  
  // A general OSType for use when setting properties on GTMCarbonEvent objects.
  // This is the "signature" as part of commandIDs, controlsIDs, and properties.
  // 'GooG'
  GTM_EXTERN const OSType kGTMCarbonFrameworkSignature;
  
  // An event handler class representing the event monitor event handler
  //
  // there is only one of these per application. This way you can put
  // event handlers directly on the dispatcher if necessary.
  @interface GTMCarbonEventMonitorHandler : GTMCarbonEventHandler
  // Accessor to get the GTMCarbonEventMonitorHandler singleton.
  //
  // Returns:
  //  pointer to the GTMCarbonEventMonitorHandler singleton.
  + (GTMCarbonEventMonitorHandler *)sharedEventMonitorHandler;
  @end
  
  // An event handler class representing the application event handler.
  //
  // there is only one of these per application. This way you can put
  // event handlers directly on the application if necessary.
  @interface GTMCarbonEventApplicationEventHandler : GTMCarbonEventHandler
  // Accessor to get the GTMCarbonEventApplicationEventHandler singleton.
  //
  // Returns:
  //  pointer to the GTMCarbonEventApplicationEventHandler singleton.
  + (GTMCarbonEventApplicationEventHandler *)sharedApplicationEventHandler;
  @end
  
  // An event handler class representing the toolbox dispatcher event handler
  //
  // there is only one of these per application. This way you can put
  // event handlers directly on the dispatcher if necessary.
  @interface GTMCarbonEventDispatcherHandler : GTMCarbonEventHandler {
   @private
    NSMutableDictionary *hotkeys_;  // Collection of registered hotkeys 
  }
  
  // Accessor to get the GTMCarbonEventDispatcherHandler singleton.
  //
  // Returns:
  //  pointer to the GTMCarbonEventDispatcherHandler singleton.
  + (GTMCarbonEventDispatcherHandler *)sharedEventDispatcherHandler;
  
  // Registers a hotkey. When the hotkey is executed by the user, target will be
  // called with selector.
  //  Arguments:
  //    keyCode - the virtual keycode of the hotkey
  //    cocoaModifiers - the modifiers that need to be used with |keyCode|. NB
  //                     that these are cocoa modifiers, so NSCommandKeyMask etc.
  //    target - instance that will get |action| called when the hotkey fires
  //    action - the method to call on |target| when the hotkey fires
  //    onPress - is YES, the hotkey fires on the keydown (usual) otherwise
  //              it fires on the key up.
  //  Returns:
  //    a EventHotKeyRef that you can use with other Carbon functions, or for
  //    unregistering the hotkey. Note that all hotkeys are unregistered
  //    automatically when an app quits. Will be NULL on failure.
  - (EventHotKeyRef)registerHotKey:(NSUInteger)keyCode 
                         modifiers:(NSUInteger)cocoaModifiers 
                            target:(id)target 
                            action:(SEL)action 
                       whenPressed:(BOOL)onPress;
  
  // Unregisters a hotkey previously registered with registerHotKey.
  //  Arguments:
  //    keyRef - the EventHotKeyRef to unregister
  - (void)unregisterHotKey:(EventHotKeyRef)keyRef;
  
  @end
  