tge/engine/platformMacCarb/macCarbEvents.cc
2017-04-17 06:17:10 -06:00

1058 lines
34 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "platformMacCarb/platformMacCarb.h"
#include "platform/event.h"
#include "platform/platformInput.h"
#include "platform/gameInterface.h"
#include "platform/platformThread.h"
#include "platform/platformVideo.h"
#include "platformMacCarb/macCarbUtil.h"
#include "platformMacCarb/macCarbEvents.h"
#include "platformMacCarb/macCarbAlerts.h"
#include "gui/core/guiCanvas.h"
#include <pthread.h>
EventHandlerRef gWinEventHandlerRef = NULL;
EventHandlerRef gAppEventHandlerRef = NULL;
EventHandlerRef gTextEventHandlerRef = NULL;
EventHandlerRef gWinMouseEventHandlerRef = NULL;
EventHandlerRef gAppMouseEventHandlerRef = NULL;
EventHandlerRef gAppAEEventHandlerRef = NULL;
EventHandlerRef gWinCloseEventHandlerRef = NULL;
EventHandlerRef gTorqueEventHandlerRef = NULL;
#pragma mark ---- Mouse Management ----
//-----------------------------------------------------------------------------
// Hides or shows the system mouse cursor, and tracks the hidden state.
void MacCarbSetHideCursor(bool shouldHide)
{
if(CGCursorIsVisible() == !shouldHide)
return;
if(shouldHide)
CGDisplayHideCursor(platState.cgDisplay);
else
CGDisplayShowCursor(platState.cgDisplay);
}
//-----------------------------------------------------------------------------
// Hides the mouse cursor when the mouse is locked, when we are in fullscreen
// mode, and when the cursor is inside the window bounds.
// Optionally takes the cursor location, in window local coords.
void MacCarbCheckHideCursor(S32 x=-1, S32 y=-1)
{
bool shouldHide = false;
if(platState.mouseLocked || Video::isFullScreen())
{
shouldHide = true;
}
else
{
Point2I win = Platform::getWindowSize();
if(x >=0 && y>=0 && x<= win.x && y<= win.y)
shouldHide = true;
}
MacCarbSetHideCursor(shouldHide && !platState.minimized);
}
//-----------------------------------------------------------------------------
// Utility func that sets the mouse position to the center of the appWindow
static void _MacCarbRecenterCapturedMouse(void)
{
if (!platState.appWindow || !platState.mouseLocked)
return;
Rect r;
Point wndCenter;
GrafPtr savePort;
// get the center of the window
GetWindowBounds(platState.appWindow,kWindowContentRgn,&r);
wndCenter.h = r.left + (r.right-r.left) / 2;
wndCenter.v = r.top + (r.bottom-r.top) / 2;
CGRect bounds = CGDisplayBounds(platState.cgDisplay);
CGPoint cgWndCenter;
cgWndCenter.x = wndCenter.h + bounds.origin.x;
cgWndCenter.y = wndCenter.v + bounds.origin.y;
CGDisplayMoveCursorToPoint(platState.cgDisplay, cgWndCenter);
}
//-----------------------------------------------------------------------------
// Utility func that gets appWindow local coords from a Carbon mouse event.
static Point _MacCarbGetMouseEventLocalCoords(EventRef theEvent)
{
// get the global coords
Point ret;
GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint,
NULL, sizeof(Point), NULL, &ret);
// return global coords if we have no window.
if(!platState.appWindow)
return ret;
// get the window's content rect
Rect bounds;
GetWindowBounds(platState.appWindow, kWindowContentRgn, &bounds);
// convert to local coords
ret.h -= bounds.left;
ret.v -= bounds.top;
return ret;
}
//-----------------------------------------------------------------------------
// Sets whether the mouse is locked to the appWindow.
// Function name is a little deceptive, but this directly affects nary a window.
void Platform::setWindowLocked(bool locked)
{
if(platState.mouseLocked == locked)
return;
platState.mouseLocked = locked;
// center the mouse when we lock.
if (platState.mouseLocked)
_MacCarbRecenterCapturedMouse();
}
#pragma mark -
#pragma mark ---- Event Handlers ----
//-----------------------------------------------------------------------------
/// Returns the Torque modifier keys of a Carbon event.
static U32 _MacCarbGetEventModifierKeys(EventRef theEvent)
{
UInt32 keyMods = 0;
GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32,
NULL, sizeof(UInt32), NULL, &keyMods);
U32 modifierKeys = 0;
if (keyMods & shiftKey) modifierKeys |= SI_LSHIFT;
if (keyMods & rightShiftKey) modifierKeys |= SI_RSHIFT;
if (keyMods & cmdKey) modifierKeys |= SI_LALT;
if (keyMods & optionKey) modifierKeys |= SI_MAC_LOPT;
if (keyMods & rightOptionKey) modifierKeys |= SI_MAC_ROPT;
if (keyMods & controlKey) modifierKeys |= SI_LCTRL;
if (keyMods & rightControlKey) modifierKeys |= SI_RCTRL;
return modifierKeys;
}
//-----------------------------------------------------------------------------
static void _OnActivate(bool activating)
{
if(activating)
{
Input::activate();
Game->refreshWindow();
platState.backgrounded = false;
pthread_kill(platState.torqueThreadId, SIGALRM);
}
else
{
Input::deactivate();
platState.backgrounded = true;
}
}
//--------------------------------------
static void _OnMouseUpDown(EventRef theEvent, bool down, U32 modifiers )
{
EventMouseButton whatButton;
GetEventParameter (theEvent, kEventParamMouseButton, typeMouseButton,
NULL, sizeof(EventMouseButton), NULL, &whatButton);
InputEvent event;
event.deviceType = MouseDeviceType;
event.deviceInst = 0;
event.objType = SI_BUTTON;
event.objInst = KEY_BUTTON0 + whatButton - 1;
event.modifier = modifiers;
event.ascii = 0;
event.action = down ? SI_MAKE : SI_BREAK;
event.fValue = down ? 1.0 : 0.0;
Game->postEvent(event);
}
//--------------------------------------
static void _OnMouseMovedDragged(EventRef theEvent, bool drag, U32 modifiers)
{
// When the mouse is locked, we deliver events in deltas.
// When not locked, we deliver in window-local coords.
// When not locked, a MouseMoveEvent instead of an InputEvent is sent.
// Discard the first 2 events after locking, to avoid spurious delta values.
static U32 discardEventCount = 2;
if(platState.mouseLocked)
{
InputEvent event;
event.deviceType = MouseDeviceType;
event.deviceInst = 0;
event.objInst = 0;
event.modifier = modifiers;
event.ascii = 0;
event.action = SI_MOVE;
// get the deltas
CGMouseDelta mdx, mdy;
CGGetLastMouseDelta(&mdx, &mdy);
// deliver the x and y events separately.
if(mdx != 0)
{
event.objType = SI_XAXIS;
event.fValue = F32(mdx);
Game->postEvent(event);
}
if(mdy != 0)
{
event.objType = SI_YAXIS;
event.fValue = F32(mdy);
Game->postEvent(event);
}
// recenter the mouse
_MacCarbRecenterCapturedMouse();
// hide the mouse if needed
MacCarbCheckHideCursor();
discardEventCount = 2;
}
else if(discardEventCount > 0)
{
discardEventCount--;
}
else
{
// convert to local window coords if possible.
Point where = _MacCarbGetMouseEventLocalCoords(theEvent);
// deliver the event
MouseMoveEvent event;
event.xPos = where.h;
event.yPos = where.v;
event.modifier = modifiers;
Game->postEvent(event);
MacCarbCheckHideCursor(where.h, where.v);
}
}
static void _OnMouseWheelMoved(EventRef theEvent, U32 modifiers)
{
InputEvent event;
S32 dWheel = 0;
GetEventParameter (theEvent, kEventParamMouseWheelDelta, typeLongInteger,
NULL, sizeof(long), NULL, &dWheel);
event.deviceType = MouseDeviceType;
event.deviceInst = 0;
event.objType = SI_ZAXIS;
event.objInst = 0;
event.modifier = modifiers;
event.ascii = 0;
event.action = SI_MOVE;
event.fValue = dWheel * kTMouseWheelMagnificationFactor;
Game->postEvent(event);
}
//--------------------------------------
static OSStatus _OnWindowEvent(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
{
OSStatus result = noErr;
// event class will always be kEventClassWindow in this handler.
UInt32 eventKind = GetEventKind(theEvent);
// the window the event is directed to
WindowRef theWind;
GetEventParameter (theEvent, kEventParamDirectObject, typeWindowRef,
NULL, sizeof(WindowRef), NULL, &theWind);
// try to snuff the event if the window is no longer valid.
if(!IsValidWindowPtr(theWind))
return noErr;
// whether to propagate the event up the chain. only some events should be
// proagated up the responder chain.
bool propagateEvent = false;
switch(eventKind)
{
case kEventWindowDrawContent:
// we must redraw the entire window
Game->refreshWindow();
break;
case kEventWindowActivated:
case kEventWindowDeactivated:
// window was switched into or out of the foreground
_OnActivate(eventKind==kEventWindowActivated);
// claim we did not handle, so that the event may propagate.
result = eventNotHandledErr;
propagateEvent = true;
break;
case kEventWindowGetClickActivation:
// this is the activating click, just update the cursor position,
// and then bump the event to the standard handler
result = eventNotHandledErr;
// if the mouse is locked, we don't need the new position.
// just skip the event & let the system feed us an activate event.
if(platState.mouseLocked)
break;
// get and update the mouse position
Point where = _MacCarbGetMouseEventLocalCoords(theEvent);
Canvas->setCursorPos(Point2I(where.h,where.v));
break;
case kEventWindowTransitionCompleted:
// a window transition has completed.
U32 transition;
GetEventParameter(theEvent, kEventParamWindowTransitionAction, typeWindowTransitionAction,
NULL, sizeof(bool), NULL, &transition);
if(transition == kWindowHideTransitionAction)
{
MacCarbSendTorqueEventToMain(kEventTorqueReleaseWindow, theWind);
}
break;
case kEventWindowBoundsChanged:
case kEventWindowZoomed:
{
Rect rectPort;
GetWindowPortBounds(theWind, &rectPort);
Platform::setWindowSize( rectPort.right-rectPort.left , rectPort.bottom-rectPort.top );
// tell the torque thread to update the AGL context
platState.ctxNeedsUpdate=true;
break;
}
case kEventWindowExpanded:
platState.minimized = false;
break;
case kEventWindowCollapsed:
platState.minimized = true;
break;
default:
AssertFatal(false,"Unknown window event");
result = eventNotHandledErr;
break;
}
// Now propagate the event to the next handler (in this case the standard window handler)
if (nextHandler && propagateEvent)
result = CallNextEventHandler (nextHandler, theEvent);
return result;
}
//--------------------------------------
OSStatus _OnWindowCloseEvent(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
{
// the window the event is directed to
WindowRef theWind;
GetEventParameter (theEvent, kEventParamDirectObject, typeWindowRef,
NULL, sizeof(WindowRef), NULL, &theWind);
// try to snuff the event if the window is no longer valid.
if(!IsValidWindowPtr(theWind))
return noErr;
// be sure we have the right event type for this handler.
U32 eventKind = GetEventKind(theEvent);
switch(eventKind)
{
case kEventWindowClose:
{
Platform::postQuitMessage(0);
return noErr;
}
default:
return eventNotHandledErr;
}
}
//--------------------------------------
//static OSStatus _OnWindowMouseEvent(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
//{
// Con::errorf("_WinMouseCarbonEventHandle");
// OSStatus result = noErr;
//
// // event class will always be kEventClassMouse in this handler.
// UInt32 eventKind = GetEventKind(theEvent);
//
// U32 modifierKeys = _MacCarbGetEventModifierKeys(theEvent);
//
// // whether to propagate the event up the chain. only some events should be
// // proagated up the responder chain.
// bool propagateEvent = false;
// bool down = false;
//
// switch(eventKind)
// {
// case kEventMouseDown:
// down = true;
// // fall through
// case kEventMouseUp:
// // mouse down must propagate so that the standard handler can
// // handle window activation.
// propagateEvent = down;
// _handleMouseUpDown(theEvent, down, modifierKeys);
// break;
//
// case kEventMouseDragged:
// down = true;
// // fall through
// case kEventMouseMoved:
// _handleMouseMovedDragged(theEvent, down, modifierKeys);
// break;
//
// case kEventMouseWheelMoved:
// _handleMouseWheelMoved(theEvent, modifierKeys);
// break;
//
// default:
// result = eventNotHandledErr;
// break;
// }
//
// // Now propagate the event to the next handler (in this case the standard window handler)
// if (nextHandler && propagateEvent)
// result = CallNextEventHandler (nextHandler, theEvent);
//
// return result;
//}
//--------------------------------------
static OSStatus _OnAppEvent(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
{
OSStatus result = noErr; // Function result
// event class will always be kEventClassApplication in this handler.
UInt32 eventKind = GetEventKind(theEvent);
// only a few events should be propagated up the responder chain.
bool propagateEvent = false;
switch(eventKind)
{
case kEventAppQuit:
// quit command from menu
Platform::postQuitMessage(0);
propagateEvent = true;
break;
case kEventAppActivated:
case kEventAppDeactivated:
// app was switched into or out of the foreground
_OnActivate(eventKind==kEventAppActivated);
// claim we did not handle, so that the event may propagate.
result = eventNotHandledErr;
break;
default:
result = eventNotHandledErr;
break;
}
if( nextHandler && propagateEvent )
result = CallNextEventHandler (nextHandler, theEvent);
return result;
}
//--------------------------------------
static OSStatus _OnAppMouseEvent(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
{
OSStatus result = noErr;
// event class will always be kEventClassMouse in this handler.
UInt32 eventKind = GetEventKind(theEvent);
U32 modifierKeys = _MacCarbGetEventModifierKeys(theEvent);
// whether to propagate the event up the chain. only some events should be
// proagated up the responder chain.
bool propagateEvent = false;
bool down = false;
switch(eventKind)
{
case kEventMouseDown:
down = true;
// fall through
case kEventMouseUp:
// mouse down must propagate so that the standard handler can
// handle window activation.
propagateEvent = down;
_OnMouseUpDown(theEvent, down, modifierKeys);
break;
case kEventMouseDragged:
down = true;
// fall through
case kEventMouseMoved:
_OnMouseMovedDragged(theEvent, down, modifierKeys);
break;
case kEventMouseWheelMoved:
_OnMouseWheelMoved(theEvent, modifierKeys);
break;
default:
result = eventNotHandledErr;
break;
}
// Now propagate the event to the next handler (in this case the standard window handler)
if (nextHandler && propagateEvent)
result = CallNextEventHandler (nextHandler, theEvent);
return result;
}
//--------------------------------------
static OSStatus _OnAppleEvent(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
{
OSStatus result = noErr; // Function result
// event class will always be kEventClassAppleEvent in this handler.
UInt32 eventKind = GetEventKind(theEvent);
// only a few events should be propagated up the responder chain.
bool propagateEvent = false;
AEEventID aeType;
GetEventParameter (theEvent, kEventParamAEEventID, typeType,
NULL, sizeof(OSType), NULL, &aeType);
switch(aeType)
{
case kAEQuitApplication:
{
Platform::postQuitMessage(0);
propagateEvent = true;
break;
}
default:
result = eventNotHandledErr;
break;
}
if( nextHandler && propagateEvent )
{
result = CallNextEventHandler (nextHandler, theEvent);
}
return result;
}
//--------------------------------------
// here we manually poll for events, and send them to the dispatcher.
// we only use this in single-threaded mode.
static void _MacCarbPollEvents()
{
EventRef carbonEvent;
EventTargetRef theTarget;
OSStatus theErr;
theTarget = GetEventDispatcherTarget();
do
{
theErr = ReceiveNextEvent(0, NULL, kEventDurationNoWait, true, &carbonEvent);
if (theErr == noErr && carbonEvent != NULL)
{
theErr = SendEventToEventTarget(carbonEvent, theTarget);
ReleaseEvent(carbonEvent);
}
}
while (theErr == noErr);
}
//--------------------------------------
void Platform::process()
{
// TODO: HID input
// ProcessMessages() manually polls for events when we are single threaded
if(Thread::getCurrentThreadId() == platState.firstThreadId)
_MacCarbPollEvents();
// Some things do not get carbon events, we must always poll for them.
// HID ( usb gamepad et al ) input, for instance.
Input::process();
if(platState.ctxNeedsUpdate)
{
aglUpdateContext(platState.ctx);
platState.ctxNeedsUpdate=false;
}
}
#pragma mark -
#pragma mark ---- Mac Torque Events ----
//--------------------------------------
void MacCarbSendTorqueEventToMain( U32 eventKind, void* userData )
{
EventRef theEvent;
CreateEvent(NULL, kEventClassTorque, eventKind, 0, kEventAttributeNone, &theEvent);
SetEventParameter(theEvent, kEventParamTorqueData, typeVoidPtr, sizeof(void*),&userData);
OSStatus err = PostEventToQueue(platState.mainEventQueue, theEvent, kEventPriorityStandard);
if(err != noErr)
Platform::forceShutdown(-1);
}
//--------------------------------------
static OSStatus _OnTorqueEvent(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
{
UInt32 eventKind = GetEventKind(theEvent);
void* torqueData;
GetEventParameter(theEvent, kEventParamTorqueData, typeVoidPtr,
NULL, sizeof(void*), NULL, &torqueData);
switch( eventKind )
{
case kEventTorqueAlert:
MacCarbRunAlertMain();
break;
case kEventTorqueFadeInWindow:
MacCarbFadeInWindow((WindowPtr)torqueData);
break;
case kEventTorqueFadeOutWindow:
MacCarbFadeAndReleaseWindow((WindowPtr)torqueData);
break;
case kEventTorqueReleaseWindow:
ReleaseWindow((WindowPtr)torqueData);
break;
case kEventTorqueShowMenuBar:
MacCarbShowMenuBar(torqueData);
break;
}
return noErr;
}
#pragma mark -
#pragma mark ---- Keyboard input ----
//--------------------------------------
void Platform::enableKeyboardTranslation(void)
{
ActivateTSMDocument(platState.tsmDoc);
platState.tsmActive=true;
}
//--------------------------------------
void Platform::disableKeyboardTranslation(void)
{
DeactivateTSMDocument(platState.tsmDoc);
platState.tsmActive=false;
}
//--------------------------------------
static void _OnRawKey(EventRef theEvent, InputEvent &torqueEvent)
{
// --------- modifiers ---------
UInt32 keyMods = 0;
GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32,
NULL, sizeof(UInt32), NULL, &keyMods);
U8 modifierKeys = 0;
if (keyMods & shiftKey) modifierKeys |= SI_LSHIFT;
if (keyMods & rightShiftKey) modifierKeys |= SI_RSHIFT;
if (keyMods & cmdKey) modifierKeys |= SI_LALT;
if (keyMods & optionKey) modifierKeys |= SI_MAC_LOPT;
if (keyMods & rightOptionKey) modifierKeys |= SI_MAC_ROPT;
if (keyMods & controlKey) modifierKeys |= SI_LCTRL;
if (keyMods & rightControlKey) modifierKeys |= SI_RCTRL;
// --
// ------- keycode & keychar -----
UInt32 keyCode = 0;
char keyChar = 0;
GetEventParameter (theEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
GetEventParameter (theEvent, kEventParamKeyMacCharCodes, typeChar,NULL, sizeof(char), NULL, &keyChar);
// --
// ------- action & value ( make, break, repeat ) -----
U8 action;
float fvalue;
U32 eventKind = GetEventKind(theEvent);
switch(eventKind)
{
case kEventRawKeyDown:
action = SI_MAKE;
fvalue = 1.0f;
break;
case kEventRawKeyUp:
action = SI_BREAK;
fvalue = 0.0f;
break;
case kEventRawKeyRepeat:
action = SI_REPEAT;
fvalue = 1.0f;
break;
default:
AssertISV(false, "Unhandled keyboard event kind!");
}
// --
//---- fill the event ----
torqueEvent.deviceType = KeyboardDeviceType;
torqueEvent.deviceInst = 0;
torqueEvent.objType = SI_KEY;
torqueEvent.objInst = TranslateOSKeyCode(keyCode);
torqueEvent.modifier = modifierKeys;
torqueEvent.ascii = 0;
torqueEvent.action = action;
torqueEvent.fValue = fvalue;
}
static OSStatus _OnTextInput(EventRef theEvent)
{
UniChar *text = NULL;
UInt32 textLen;
U32 charCount = 0;
EventRef rawEvent;
InputEvent rawTorqueEvent;
rawTorqueEvent.objInst = 0;
rawTorqueEvent.modifier = 0;
rawTorqueEvent.action = SI_MAKE;
rawTorqueEvent.fValue = 1.0f;
U32 eventKind = GetEventKind(theEvent);
switch(eventKind)
{
case kEventTextInputUnicodeForKeyEvent:
{
// get the input string from the text input event
// first get the number of bytes required
GetEventParameter( theEvent, kEventParamTextInputSendText, typeUnicodeText, NULL, 0, &textLen, NULL);
charCount = textLen / sizeof(UniChar);
text = new UniChar[charCount];
// now that we've allocated space, get the buffer of text from the input method or keyboard.
GetEventParameter( theEvent, kEventParamTextInputSendText, typeUnicodeText, NULL, textLen, NULL, text);
// now trap the raw event.
OSStatus err =
GetEventParameter( theEvent, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(EventRef), NULL, &rawEvent);
if( err==noErr)
{
_OnRawKey(rawEvent,rawTorqueEvent);
}
break;
}
default: // if we somehow get the wrong kind of event, let someone else handle it.
{
return eventNotHandledErr;
}
}
// make torque events to enter that string.
InputEvent torqueEvent;
torqueEvent.deviceType = KeyboardDeviceType;
torqueEvent.deviceInst = 0;
torqueEvent.objType = SI_KEY;
torqueEvent.objInst = rawTorqueEvent.objInst;
torqueEvent.modifier = rawTorqueEvent.modifier;
torqueEvent.action = rawTorqueEvent.action;
torqueEvent.fValue = rawTorqueEvent.fValue;
for( int i=0; i < charCount; i++)
{
torqueEvent.ascii = text[i];
Game->postEvent(torqueEvent);
}
return noErr;
}
//-----------------------------------------------------------------------------
static OSStatus _OnRawModifiers(EventRef theEvent)
{
static U32 oldModState = 0L;
U32 mods;
GetEventParameter(theEvent, kEventParamKeyModifiers,
typeUInt32, NULL, sizeof(UInt32), NULL, &mods);
oldModState = mods;
return noErr;
}
//--------------------------------------
static OSStatus _OnKeyboardEvent(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
{
// be sure we have the right event type for this handler.
U32 eventClass = GetEventClass(theEvent);
U32 eventKind = GetEventKind(theEvent);
switch(eventClass)
{
case kEventClassTextInput:
{
return _OnTextInput(theEvent);
break;
}
case kEventClassKeyboard:
{
if(eventKind == kEventRawKeyModifiersChanged)
{
return _OnRawModifiers(theEvent);
break;
}
InputEvent keyEvent;
_OnRawKey( theEvent, keyEvent);
// This is hackish and requires explanation:
// We don't get key-up events as text events, only key-down and key-repeat events.
// So we explicitly post key-up events, even if text translation is active.
if(platState.tsmActive && keyEvent.action != SI_BREAK)
return eventNotHandledErr;
Game->postEvent(keyEvent);
return noErr;
break;
}
default:
return eventNotHandledErr;
}
}
#pragma mark -
#pragma mark ---- Event Install/Remove ----
//--------------------------------------
// Install event handlers for communication between Torque and the first thread.
// Since the first thread must handle certain events and system calls, we have
// to have a way to send commands to that very first thread.
void MacCarbInstallTorqueCarbonEventHandlers()
{
// list the events we want to recieve in each event handler
int c = 0;
const int MAX_EVENT_TYPES = 16; // arbitrary value.
static EventTypeSpec torqueEventTypes[MAX_EVENT_TYPES];
static EventHandlerUPP torqueHandlerUPP = NULL;
static int torqueEventCount = 0;
if (torqueHandlerUPP==NULL)
{
c = 0;
torqueEventTypes[c].eventClass = kEventClassTorque;
torqueEventTypes[c++].eventKind = kEventTorqueAlert;
torqueEventTypes[c].eventClass = kEventClassTorque;
torqueEventTypes[c++].eventKind = kEventTorqueFadeInWindow;
torqueEventTypes[c].eventClass = kEventClassTorque;
torqueEventTypes[c++].eventKind = kEventTorqueFadeOutWindow;
torqueEventTypes[c].eventClass = kEventClassTorque;
torqueEventTypes[c++].eventKind = kEventTorqueReleaseWindow;
torqueEventTypes[c].eventClass = kEventClassTorque;
torqueEventTypes[c++].eventKind = kEventTorqueShowMenuBar;
torqueHandlerUPP = NewEventHandlerUPP(_OnTorqueEvent);
torqueEventCount = c;
}
// we only install this one once, because we never remove it.
if(!gTorqueEventHandlerRef)
InstallEventHandler(GetApplicationEventTarget(), torqueHandlerUPP, torqueEventCount, torqueEventTypes, NULL, &gTorqueEventHandlerRef);
}
//--------------------------------------
void MacCarbInstallCarbonEventHandlers()
{
// we do not have an appWindow if we are in fullscreen mode - be aware.
EventTargetRef winTarg = NULL;
if(platState.appWindow)
winTarg = GetWindowEventTarget(platState.appWindow);
// list the events we want to recieve in each event handler
int c = 0;
const int MAX_EVENT_TYPES = 16; // arbitrary value.
static EventTypeSpec winEventTypes[MAX_EVENT_TYPES];
static EventHandlerUPP winHandlerUPP = NULL;
static int winEventCount = 0;
static EventTypeSpec appEventTypes[MAX_EVENT_TYPES];
static EventHandlerUPP appHandlerUPP = NULL;
static int appEventCount = 0;
static EventTypeSpec appMouseEventTypes[MAX_EVENT_TYPES];
static EventHandlerUPP appMouseHandlerUPP = NULL;
static int appMouseEventCount = 0;
static EventTypeSpec appAEEventTypes[MAX_EVENT_TYPES];
static EventHandlerUPP appAEHandlerUPP = NULL;
static int appAEEventCount = 0;
static EventTypeSpec textEventTypes[MAX_EVENT_TYPES];
static EventHandlerUPP textHandlerUPP = NULL;
static int textEventCount = 0;
static EventTypeSpec closeEventTypes[MAX_EVENT_TYPES];
static EventHandlerUPP closeEventHandlerUPP = NULL;
static int closeEventCount = 0;
if(closeEventHandlerUPP == NULL)
{
c = 0;
closeEventTypes[c].eventClass = kEventClassWindow;
closeEventTypes[c++].eventKind = kEventWindowClose;
closeEventTypes[c].eventClass = kEventClassWindow;
closeEventTypes[c++].eventKind = kEventWindowClosed;
closeEventHandlerUPP = NewEventHandlerUPP(_OnWindowCloseEvent);
closeEventCount = c;
}
if(textHandlerUPP==NULL)
{
c = 0;
textEventTypes[c].eventClass = kEventClassTextInput;
textEventTypes[c++].eventKind = kEventTextInputUnicodeForKeyEvent;
// we would split these off to another Do... handler, but I want all keyboard interaction
// to go through a single control point for the moment. -paxorr
textEventTypes[c].eventClass = kEventClassKeyboard;
textEventTypes[c++].eventKind = kEventRawKeyDown;
textEventTypes[c].eventClass = kEventClassKeyboard;
textEventTypes[c++].eventKind = kEventRawKeyUp;
textEventTypes[c].eventClass = kEventClassKeyboard;
textEventTypes[c++].eventKind = kEventRawKeyRepeat;
// these should perhaps have their own Do... handler as well.
textEventTypes[c].eventClass = kEventClassKeyboard;
textEventTypes[c++].eventKind = kEventRawKeyModifiersChanged;
textHandlerUPP = NewEventHandlerUPP(_OnKeyboardEvent);
textEventCount = c;
}
if (winHandlerUPP==NULL)
{
c = 0;
winEventTypes[c].eventClass = kEventClassWindow;
winEventTypes[c++].eventKind = kEventWindowDrawContent;
winEventTypes[c].eventClass = kEventClassWindow;
winEventTypes[c++].eventKind = kEventWindowBoundsChanged;
winEventTypes[c].eventClass = kEventClassWindow;
winEventTypes[c++].eventKind = kEventWindowZoomed;
// winEventTypes[c].eventClass = kEventClassWindow;
// winEventTypes[c++].eventKind = kEventWindowActivated;
// winEventTypes[c].eventClass = kEventClassWindow;
// winEventTypes[c++].eventKind = kEventWindowDeactivated;
winEventTypes[c].eventClass = kEventClassWindow;
winEventTypes[c++].eventKind = kEventWindowClose;
winEventTypes[c].eventClass = kEventClassWindow;
winEventTypes[c++].eventKind = kEventWindowGetClickActivation;
winEventTypes[c].eventClass = kEventClassWindow;
winEventTypes[c++].eventKind = kEventWindowTransitionCompleted;
winEventTypes[c].eventClass = kEventClassWindow;
winEventTypes[c++].eventKind = kEventWindowCollapsed;
winEventTypes[c].eventClass = kEventClassWindow;
winEventTypes[c++].eventKind = kEventWindowExpanded;
winHandlerUPP = NewEventHandlerUPP(_OnWindowEvent);
winEventCount = c;
}
if (appHandlerUPP==NULL)
{
c = 0;
appEventTypes[c].eventClass = kEventClassApplication;
appEventTypes[c++].eventKind = kEventAppQuit;
appEventTypes[c].eventClass = kEventClassApplication;
appEventTypes[c++].eventKind = kEventAppActivated;
appEventTypes[c].eventClass = kEventClassApplication;
appEventTypes[c++].eventKind = kEventAppDeactivated;
appHandlerUPP = NewEventHandlerUPP(_OnAppEvent);
appEventCount = c;
}
if (appMouseHandlerUPP==NULL)
{
c = 0;
appMouseEventTypes[c].eventClass = kEventClassMouse;
appMouseEventTypes[c++].eventKind = kEventMouseDown;
appMouseEventTypes[c].eventClass = kEventClassMouse;
appMouseEventTypes[c++].eventKind = kEventMouseUp;
appMouseEventTypes[c].eventClass = kEventClassMouse;
appMouseEventTypes[c++].eventKind = kEventMouseMoved;
appMouseEventTypes[c].eventClass = kEventClassMouse;
appMouseEventTypes[c++].eventKind = kEventMouseDragged;
appMouseEventTypes[c].eventClass = kEventClassMouse;
appMouseEventTypes[c++].eventKind = kEventMouseWheelMoved;
appMouseHandlerUPP = NewEventHandlerUPP(_OnAppMouseEvent);
appMouseEventCount = c;
}
if (appAEHandlerUPP==NULL)
{
c = 0;
appAEEventTypes[c].eventClass = kEventClassAppleEvent;
appAEEventTypes[c++].eventKind = kEventAppleEvent; // it's always an appleEvent
appAEHandlerUPP = NewEventHandlerUPP(_OnAppleEvent);
appAEEventCount = c;
}
// this installs at the window level
if(platState.appWindow)
{
// this installs into the window -- window doesn't always get all events, such as App events
InstallEventHandler(winTarg, winHandlerUPP, winEventCount, winEventTypes, NULL, &gWinEventHandlerRef);
InstallEventHandler(winTarg, closeEventHandlerUPP, closeEventCount, closeEventTypes, NULL, &gWinCloseEventHandlerRef);
}
// this installs at the app level.
InstallEventHandler(GetApplicationEventTarget(), appHandlerUPP, appEventCount, appEventTypes, NULL, &gAppEventHandlerRef);
InstallEventHandler(GetApplicationEventTarget(), appMouseHandlerUPP, appMouseEventCount, appMouseEventTypes, NULL, &gAppMouseEventHandlerRef);
InstallEventHandler(GetApplicationEventTarget(), appAEHandlerUPP, appAEEventCount, appAEEventTypes, NULL, &gAppAEEventHandlerRef);
// this installs a handler for unicode text input
// we install on the app only because we have just 1 window.
InstallEventHandler(GetApplicationEventTarget(), textHandlerUPP, textEventCount, textEventTypes, NULL, &gTextEventHandlerRef);
}
void MacCarbRemoveCarbonEventHandlers()
{
RemoveEventHandler(gWinEventHandlerRef);
RemoveEventHandler(gAppEventHandlerRef);
RemoveEventHandler(gTextEventHandlerRef);
RemoveEventHandler(gWinMouseEventHandlerRef);
RemoveEventHandler(gAppMouseEventHandlerRef);
RemoveEventHandler(gAppAEEventHandlerRef);
RemoveEventHandler(gWinCloseEventHandlerRef);
}