00001
00002
00003
00004 #include "aglEventHandler.h"
00005
00006 #include "global.h"
00007 #include "log.h"
00008 #include "window.h"
00009 #include "aglWindow.h"
00010
00011 using namespace eq::base;
00012 using namespace std;
00013
00014 namespace eq
00015 {
00016 AGLEventHandler AGLEventHandler::_handler;
00017
00018 AGLEventHandler* AGLEventHandler::get()
00019 {
00020 return &_handler;
00021 }
00022
00023 AGLEventHandler::AGLEventHandler()
00024 : _lastDX( 0 ),
00025 _lastDY( 0 )
00026 {
00027 }
00028
00029 void AGLEventHandler::registerWindow( AGLWindowIF* window )
00030 {
00031 const WindowRef carbonWindow = window->getCarbonWindow();
00032 if( !carbonWindow )
00033 {
00034 EQWARN << "Can't add window without native Carbon window to AGL event "
00035 << "handler" << endl;
00036 return;
00037 }
00038
00039 Global::enterCarbon();
00040 EventHandlerUPP eventHandler = NewEventHandlerUPP(
00041 eq::AGLEventHandler::_handleEventUPP );
00042 EventTypeSpec eventType[] = {
00043 { kEventClassWindow, kEventWindowBoundsChanged },
00044 { kEventClassWindow, kEventWindowUpdate },
00045 { kEventClassWindow, kEventWindowDrawContent },
00046 { kEventClassWindow, kEventWindowClosed },
00047 { kEventClassWindow, kEventWindowHidden },
00048 { kEventClassWindow, kEventWindowCollapsed },
00049 { kEventClassWindow, kEventWindowShown },
00050 { kEventClassWindow, kEventWindowExpanded },
00051 { kEventClassMouse, kEventMouseMoved },
00052 { kEventClassMouse, kEventMouseDragged },
00053 { kEventClassMouse, kEventMouseDown },
00054 { kEventClassMouse, kEventMouseUp },
00055 { kEventClassKeyboard, kEventRawKeyDown },
00056 { kEventClassKeyboard, kEventRawKeyUp },
00057 { kEventClassKeyboard, kEventRawKeyRepeat }
00058 };
00059
00060 EventHandlerRef& carbonEventHandler = window->getCarbonEventHandler();
00061 InstallWindowEventHandler( carbonWindow, eventHandler,
00062 sizeof( eventType ) / sizeof( EventTypeSpec ),
00063 eventType, window, &carbonEventHandler );
00064 Global::leaveCarbon();
00065
00066 EQINFO << "Installed event handler for carbon window " << carbonWindow
00067 << endl;
00068 }
00069
00070 void AGLEventHandler::deregisterWindow( AGLWindowIF* window )
00071 {
00072 Global::enterCarbon();
00073 EventHandlerRef& eventHandler = window->getCarbonEventHandler();
00074 RemoveEventHandler( eventHandler );
00075 eventHandler = 0;
00076 Global::leaveCarbon();
00077 }
00078
00079 pascal OSStatus AGLEventHandler::_handleEventUPP(
00080 EventHandlerCallRef nextHandler, EventRef event, void* userData )
00081 {
00082 AGLWindowIF* window = static_cast< AGLWindowIF* >( userData );
00083 AGLEventHandler* handler = get();
00084
00085 handler->_handleEvent( event, window );
00086
00087
00088
00089 return CallNextEventHandler( nextHandler, event );
00090 }
00091
00092 bool AGLEventHandler::_handleEvent( EventRef event, AGLWindowIF* window )
00093 {
00094 switch( GetEventClass( event ))
00095 {
00096 case kEventClassWindow:
00097 return _handleWindowEvent( event, window );
00098 case kEventClassMouse:
00099 return _handleMouseEvent( event, window );
00100 case kEventClassKeyboard:
00101 return _handleKeyEvent( event, window );
00102 default:
00103 EQINFO << "Unknown event class " << GetEventClass( event ) << endl;
00104 return false;
00105 }
00106 }
00107
00108 bool AGLEventHandler::_handleWindowEvent( EventRef event, AGLWindowIF* osWindow)
00109 {
00110 AGLWindowEvent windowEvent;
00111 windowEvent.carbonEventRef = event;
00112 Window* const window = osWindow->getWindow();
00113
00114 Rect rect;
00115 WindowRef carbonWindow = osWindow->getCarbonWindow();
00116 GetWindowPortBounds( carbonWindow, &rect );
00117 windowEvent.resize.x = rect.top;
00118 windowEvent.resize.y = rect.left;
00119 windowEvent.resize.h = rect.bottom - rect.top;
00120 windowEvent.resize.w = rect.right - rect.left;
00121
00122 switch( GetEventKind( event ))
00123 {
00124 case kEventWindowBoundsChanged:
00125 windowEvent.type = Event::WINDOW_RESIZE;
00126 break;
00127
00128 case kEventWindowUpdate:
00129 BeginUpdate( carbonWindow );
00130 EndUpdate( carbonWindow );
00131
00132 case kEventWindowDrawContent:
00133 windowEvent.type = Event::EXPOSE;
00134 break;
00135
00136 case kEventWindowClosed:
00137 windowEvent.type = Event::WINDOW_CLOSE;
00138 break;
00139
00140 case kEventWindowHidden:
00141 case kEventWindowCollapsed:
00142 windowEvent.type = Event::WINDOW_HIDE;
00143 break;
00144
00145 case kEventWindowShown:
00146 case kEventWindowExpanded:
00147 windowEvent.type = Event::WINDOW_SHOW;
00148 if( carbonWindow == FrontNonFloatingWindow( ))
00149 SetUserFocusWindow( carbonWindow );
00150 break;
00151
00152 default:
00153 EQINFO << "Unhandled window event " << GetEventKind( event ) <<endl;
00154 windowEvent.type = Event::UNKNOWN;
00155 break;
00156 }
00157 windowEvent.originator = window->getID();
00158
00159 EQLOG( LOG_EVENTS ) << "received event: " << windowEvent << endl;
00160 return osWindow->processEvent( windowEvent );
00161 }
00162
00163 bool AGLEventHandler::_handleMouseEvent( EventRef event, AGLWindowIF* osWindow )
00164 {
00165 HIPoint pos;
00166 AGLWindowEvent windowEvent;
00167
00168 windowEvent.carbonEventRef = event;
00169 Window* const window = osWindow->getWindow();
00170
00171 const bool decoration =
00172 window->getIAttribute( Window::IATTR_HINT_DECORATION ) != OFF;
00173 const int32_t menuHeight = decoration ? EQ_AGL_MENUBARHEIGHT : 0 ;
00174
00175 switch( GetEventKind( event ))
00176 {
00177 case kEventMouseMoved:
00178 case kEventMouseDragged:
00179 windowEvent.type = Event::POINTER_MOTION;
00180 windowEvent.pointerMotion.button = PTR_BUTTON_NONE;
00181
00182
00183 windowEvent.pointerMotion.buttons =
00184 GetCurrentEventButtonState();
00185
00186 if( windowEvent.pointerMotion.buttons == PTR_BUTTON1 )
00187 {
00188
00189 uint32_t keys = 0;
00190 GetEventParameter( event, kEventParamKeyModifiers,
00191 typeUInt32, 0, sizeof( keys ), 0, &keys );
00192 if( keys & controlKey )
00193 windowEvent.pointerMotion.buttons = PTR_BUTTON3;
00194 else if( keys & optionKey )
00195 windowEvent.pointerMotion.buttons = PTR_BUTTON2;
00196 }
00197
00198 GetEventParameter( event, kEventParamWindowMouseLocation,
00199 typeHIPoint, 0, sizeof( pos ), 0,
00200 &pos );
00201 if( pos.y < menuHeight )
00202 return false;
00203
00204 windowEvent.pointerMotion.x = static_cast< int32_t >( pos.x );
00205 windowEvent.pointerMotion.y = static_cast< int32_t >( pos.y ) -
00206 menuHeight;
00207
00208 GetEventParameter( event, kEventParamMouseDelta,
00209 typeHIPoint, 0, sizeof( pos ), 0,
00210 &pos );
00211 windowEvent.pointerMotion.dx = static_cast< int32_t >( pos.x );
00212 windowEvent.pointerMotion.dy = static_cast< int32_t >( pos.y );
00213
00214 _lastDX = windowEvent.pointerMotion.dx;
00215 _lastDY = windowEvent.pointerMotion.dy;
00216
00217 _getRenderContext( window, windowEvent );
00218 break;
00219
00220 case kEventMouseDown:
00221 windowEvent.type = Event::POINTER_BUTTON_PRESS;
00222 windowEvent.pointerButtonPress.buttons =
00223 GetCurrentEventButtonState();
00224 windowEvent.pointerButtonPress.button =
00225 _getButtonAction( event );
00226
00227 if( windowEvent.pointerMotion.buttons == PTR_BUTTON1 )
00228 {
00229
00230 uint32_t keys = 0;
00231 GetEventParameter( event, kEventParamKeyModifiers,
00232 typeUInt32, 0, sizeof( keys ), 0, &keys );
00233 if( keys & controlKey )
00234 windowEvent.pointerMotion.buttons = PTR_BUTTON3;
00235 else if( keys & optionKey )
00236 windowEvent.pointerMotion.buttons = PTR_BUTTON2;
00237 }
00238
00239 GetEventParameter( event, kEventParamWindowMouseLocation,
00240 typeHIPoint, 0, sizeof( pos ), 0,
00241 &pos );
00242 if( pos.y < menuHeight )
00243 return false;
00244
00245 windowEvent.pointerButtonPress.x =
00246 static_cast< int32_t >( pos.x );
00247 windowEvent.pointerButtonPress.y =
00248 static_cast< int32_t >( pos.y ) - menuHeight;
00249
00250 windowEvent.pointerButtonPress.dx = _lastDX;
00251 windowEvent.pointerButtonPress.dy = _lastDY;
00252 _lastDX = 0;
00253 _lastDY = 0;
00254
00255 _getRenderContext( window, windowEvent );
00256 break;
00257
00258 case kEventMouseUp:
00259 windowEvent.type = Event::POINTER_BUTTON_RELEASE;
00260 windowEvent.pointerButtonRelease.buttons =
00261 GetCurrentEventButtonState();
00262 windowEvent.pointerButtonRelease.button =
00263 _getButtonAction( event );
00264
00265 if( windowEvent.pointerMotion.buttons == PTR_BUTTON1 )
00266 {
00267
00268 uint32_t keys = 0;
00269 GetEventParameter( event, kEventParamKeyModifiers,
00270 typeUInt32, 0, sizeof( keys ), 0, &keys );
00271 if( keys & controlKey )
00272 windowEvent.pointerMotion.buttons = PTR_BUTTON3;
00273 else if( keys & optionKey )
00274 windowEvent.pointerMotion.buttons = PTR_BUTTON2;
00275 }
00276
00277 GetEventParameter( event, kEventParamWindowMouseLocation,
00278 typeHIPoint, 0, sizeof( pos ), 0,
00279 &pos );
00280 if( pos.y < menuHeight )
00281 return false;
00282
00283 windowEvent.pointerButtonRelease.x =
00284 static_cast< int32_t>( pos.x );
00285 windowEvent.pointerButtonRelease.y =
00286 static_cast< int32_t>( pos.y ) - menuHeight;
00287
00288 windowEvent.pointerButtonRelease.dx = _lastDX;
00289 windowEvent.pointerButtonRelease.dy = _lastDY;
00290 _lastDX = 0;
00291 _lastDY = 0;
00292
00293 _getRenderContext( window, windowEvent );
00294 break;
00295
00296 default:
00297 EQINFO << "Unhandled mouse event " << GetEventKind( event ) << endl;
00298 windowEvent.type = Event::UNKNOWN;
00299 break;
00300 }
00301 windowEvent.originator = window->getID();
00302
00303 EQLOG( LOG_EVENTS ) << "received event: " << windowEvent << endl;
00304 return osWindow->processEvent( windowEvent );
00305 }
00306
00307 bool AGLEventHandler::_handleKeyEvent( EventRef event, AGLWindowIF* osWindow )
00308 {
00309 AGLWindowEvent windowEvent;
00310
00311 windowEvent.carbonEventRef = event;
00312 Window* const window = osWindow->getWindow();
00313
00314 switch( GetEventKind( event ))
00315 {
00316 case kEventRawKeyDown:
00317 case kEventRawKeyRepeat:
00318 windowEvent.type = Event::KEY_PRESS;
00319 windowEvent.keyPress.key = _getKey( event );
00320 break;
00321
00322 case kEventRawKeyUp:
00323 windowEvent.type = Event::KEY_RELEASE;
00324 windowEvent.keyPress.key = _getKey( event );
00325 break;
00326
00327 default:
00328 EQINFO << "Unhandled keyboard event " << GetEventKind( event )
00329 << endl;
00330 windowEvent.type = Event::UNKNOWN;
00331 break;
00332 }
00333 windowEvent.originator = window->getID();
00334
00335 EQLOG( LOG_EVENTS ) << "received event: " << windowEvent << endl;
00336 return osWindow->processEvent( windowEvent );
00337 }
00338
00339 uint32_t AGLEventHandler::_getButtonAction( EventRef event )
00340 {
00341 EventMouseButton button;
00342 GetEventParameter( event, kEventParamMouseButton,
00343 typeMouseButton, 0, sizeof( button ), 0,
00344 &button );
00345
00346 switch( button )
00347 {
00348 case kEventMouseButtonPrimary: return PTR_BUTTON1;
00349 case kEventMouseButtonSecondary: return PTR_BUTTON2;
00350 case kEventMouseButtonTertiary: return PTR_BUTTON3;
00351 default: return PTR_BUTTON_NONE;
00352 }
00353 }
00354
00355 uint32_t AGLEventHandler::_getKey( EventRef event )
00356 {
00357 unsigned char key;
00358 GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, 0,
00359 sizeof( char ), 0, &key );
00360 switch( key )
00361 {
00362 case kEscapeCharCode: return KC_ESCAPE;
00363 case kBackspaceCharCode: return KC_BACKSPACE;
00364 case kReturnCharCode: return KC_RETURN;
00365 case kTabCharCode: return KC_TAB;
00366 case kHomeCharCode: return KC_HOME;
00367 case kLeftArrowCharCode: return KC_LEFT;
00368 case kUpArrowCharCode: return KC_UP;
00369 case kRightArrowCharCode: return KC_RIGHT;
00370 case kDownArrowCharCode: return KC_DOWN;
00371 case kPageUpCharCode: return KC_PAGE_UP;
00372 case kPageDownCharCode: return KC_PAGE_DOWN;
00373 case kEndCharCode: return KC_END;
00374 #if 0
00375 case XK_F1: return KC_F1;
00376 case XK_F2: return KC_F2;
00377 case XK_F3: return KC_F3;
00378 case XK_F4: return KC_F4;
00379 case XK_F5: return KC_F5;
00380 case XK_F6: return KC_F6;
00381 case XK_F7: return KC_F7;
00382 case XK_F8: return KC_F8;
00383 case XK_F9: return KC_F9;
00384 case XK_F10: return KC_F10;
00385 case XK_F11: return KC_F11;
00386 case XK_F12: return KC_F12;
00387 case XK_F13: return KC_F13;
00388 case XK_F14: return KC_F14;
00389 case XK_F15: return KC_F15;
00390 case XK_F16: return KC_F16;
00391 case XK_F17: return KC_F17;
00392 case XK_F18: return KC_F18;
00393 case XK_F19: return KC_F19;
00394 case XK_F20: return KC_F20;
00395 case XK_Shift_L: return KC_SHIFT_L;
00396 case XK_Shift_R: return KC_SHIFT_R;
00397 case XK_Control_L: return KC_CONTROL_L;
00398 case XK_Control_R: return KC_CONTROL_R;
00399 case XK_Alt_L: return KC_ALT_L;
00400 case XK_Alt_R: return KC_ALT_R;
00401 #endif
00402
00403 default:
00404
00405 if(( key >= ' ' && key <= '~' ) ||
00406 ( key >= 0xa0 ))
00407
00408 return key;
00409
00410 EQWARN << "Unrecognized key " << key << endl;
00411 return KC_VOID;
00412 }
00413 }
00414 }