-
-// TODO: Do I have to make the event handlers "pascal", or use "NewEventHandlerUPP"?
-pascal static OSStatus CarbonSurfaceEventHandler( EventHandlerCallRef handler, EventRef event, void* data ) {
- UInt32 eventClass = GetEventClass( event );
- UInt32 eventKind = GetEventKind( event );
- OSStatus result = eventNotHandledErr;
- org::xwt::plat::Carbon$CarbonSurface* surface = (org::xwt::plat::Carbon$CarbonSurface*)data;
-
- //JvSynchronize dummy( surface );
-
- switch(eventClass) {
- case kEventClassWindow:
- switch(eventKind)
- {
- case kEventWindowUpdate:
- {
- //fprintf( stderr, "window update " );
-
- // Create the graphics context
- result = CreateCGContextForPort(GetWindowPort( (WindowRef) surface->window), (CGContextRef*) &surface->gc);
- assert( result == noErr && surface->gc != NULL );
-
- // Quartz uses the bottom left as its origin. Translate to use the top left.
- Rect bounds;
- GetWindowBounds( (WindowRef) surface->window, kWindowContentRgn, &bounds );
- assert( result == noErr );
- CGContextTranslateCTM( (CGContextRef) surface->gc, 0, bounds.bottom - bounds.top );
- CGContextScaleCTM( (CGContextRef) surface->gc, 1, -1 );
-
- // Convert the context to a CGRect with local coordinates
- CGRect contentBounds = CGRectMake( 0, 0, bounds.right - bounds.left, bounds.bottom - bounds.top );
-
- //PRINT_CGRECT( contentBounds );
-
- // Get the invalid region
- Rect globalInvalidRect;
- result = GetWindowBounds( (WindowRef) surface->window, kWindowUpdateRgn, &globalInvalidRect );
- assert( result == noErr );
-
- CGRect invalidRect = CGRectMake( globalInvalidRect.left - bounds.left, globalInvalidRect.top - bounds.top, globalInvalidRect.right - globalInvalidRect.left, globalInvalidRect.bottom - globalInvalidRect.top );
-
- //invalidRect = CGRectIntersection( invalidRect, contentBounds );
-
- //PRINT_CGRECT( invalidRect );
-
- BeginUpdate( (WindowRef) surface->window );
-
- // Erase the region with white
- // TODO: Draw the window background instead
- //result = SetThemeWindowBackground( (WindowRef) surface->window, ThemeBrush inBrush, true );
- CGContextSetRGBFillColor( (CGContextRef) surface->gc, 1.0, 1.0, 1.0, 1.0 );
- CGContextFillRect( (CGContextRef) surface->gc, invalidRect );
-
- //CGContextSetRGBFillColor( (CGContextRef) surface->gc, red, green, blue, 0.5 );
- //CGContextFillRect( (CGContextRef) surface->gc, CGRectMake( 0, 0, (bounds.right - bounds.left), (bounds.bottom - bounds.top) ) );
- // Add the invalid region to XWT's dirty regions
- surface->Dirty( (jint) invalidRect.origin.x, (jint) invalidRect.origin.y, (jint) invalidRect.size.width, (jint) invalidRect.size.height );
- // Then tell it to actually do the drawing
- surface->blitDirtyScreenRegions();
-
- EndUpdate( (WindowRef) surface->window );
-
- // Free the context
- CGContextFlush( (CGContextRef) surface->gc );
- CGContextRelease( (CGContextRef) surface->gc );
- surface->gc = NULL;
- result = noErr;
- break;
- }
-
- case kEventWindowBoundsChanged:
- {
- // We can't use the event parameter: it is the window bounds, not the content area bounds
- HIRect currentBounds;
- result = GetEventParameter( event, kEventParamCurrentBounds, typeHIRect, NULL, sizeof( currentBounds ), NULL, ¤tBounds );
- assert( result == noErr );
-
- // Get the event attributes to determine if size and/or origin have changed
- UInt32 attributes;
- result = GetEventParameter( event, kEventParamAttributes, typeUInt32, NULL, sizeof( attributes ), NULL, &attributes );
- assert( result == noErr );
-
- if ( attributes & kWindowBoundsChangeSizeChanged ) {
- // If maximize is set, unset it
- if ( attributes & kWindowBoundsChangeUserResize && surface->maximized ) {
- //fprintf( stderr, "maximized = 0\n" );
- surface->Maximized( false );
- }
-
- //fprintf( stderr, "size changed\n" );
- surface->SizeChange( (jint) currentBounds.size.width, (jint) currentBounds.size.height );
-
-
- }
-
- if ( attributes & kWindowBoundsChangeOriginChanged ) {
- //fprintf( stderr, "origin changed\n" );
- surface->PosChange( (jint) currentBounds.origin.x, (jint) currentBounds.origin.y );
- }
-
- result = noErr;
- break;
- }
-
- case kEventWindowActivated:
- case kEventWindowDeactivated:
- {
- //fprintf( stderr, "focus = %d\n", (eventKind == kEventWindowActivated) );
- surface->Focused( (eventKind == kEventWindowActivated) );
- result = noErr;
- break;
- }
-
- case kEventWindowZoomed:
- {
- // Toggle maximized whenever we recieve this event
- //fprintf( stderr, "maximized: %d\n", ! surface->maximized );
- surface->Maximized( ! surface->maximized );
- result = noErr;
- break;
- }
-
- case kEventWindowCollapsed:
- {
- //fprintf( stderr, "minimized true\n" );
- surface->Minimized( true );
- result = noErr;
- break;
- }
-
- case kEventWindowExpanded:
- {
- //fprintf( stderr, "minimized false\n" );
- surface->Minimized( false );
- result = noErr;
- break;
- }
-
- case kEventWindowClose:
- {
- //fprintf( stderr, "close\n" );
- surface->Close();
- result = noErr;
- break;
- }
- default:
- throw new java::lang::Error(JvNewStringLatin1("Unhandled Window Event"));
- }
- break;
-
- case kEventClassMouse:
- {
- HIPoint where;
- result = GetEventParameter( event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(where), NULL, &where );
- assert( result == noErr );
-
- // Create a hit test event to ask the standard window event handler where this press is
- EventRef hitTest;
- result = CreateEvent( NULL, kEventClassWindow, kEventWindowHitTest, 0, kEventAttributeNone, &hitTest );
- assert( result == noErr );
-
- result = SetEventParameter( hitTest, kEventParamMouseLocation, typeHIPoint, sizeof(where), &where );
- assert( result == noErr );
-
- result = SetEventParameter( hitTest, kEventParamDirectObject, typeWindowRef, sizeof(surface->window), &surface->window );
- assert( result == noErr );
-
- result = SendEventToEventTarget( hitTest, GetWindowEventTarget( (WindowRef) surface->window ) );
- assert( result == noErr );
-
- WindowDefPartCode part;
- result = GetEventParameter( hitTest, kEventParamWindowDefPart, typeWindowDefPartCode, NULL, sizeof(part), NULL, &part );
- assert( result == noErr );
-
- ReleaseEvent( hitTest );
- hitTest = NULL;
-
- // ignore the event if it is not in the content region.
- if ( part != wInContent )
- {
- return eventNotHandledErr;
- }
-
- // TODO: Can I get the content region's bounds as an HIRect?
- Rect bounds;
- GetWindowBounds( (WindowRef) surface->window, kWindowContentRgn, &bounds );
- assert( result == noErr );
- // Convert the context to a CGRect with local coordinates
- CGRect contentBounds = CGRectMake( bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top );
-
- // Now convert the point to content area relative coordinates:
- where.x -= contentBounds.origin.x;
- where.y -= contentBounds.origin.y;
-
- switch ( eventKind )
- {
- case kEventMouseDown:
- {
- //fprintf( stderr, "mouse down (%f, %f)\n", where.x, where.y );
- EventMouseButton mouseButton;
- result = GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton );
- assert( result == noErr );
-
- surface->Press( mouseButton );
- result = eventNotHandledErr;
- break;
- }
-
- case kEventMouseUp:
- {
- //fprintf( stderr, "mouse up (%f, %f)\n", where.x, where.y );
- EventMouseButton mouseButton;
- result = GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(mouseButton), NULL, &mouseButton );
- assert( result == noErr );
-
- UInt32 clickCount;
- result = GetEventParameter( event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount );
- assert( result == noErr );
-
- surface->Release( mouseButton );
-
- // deliver click/double click events
- if ( clickCount == 1 ) {
- //fprintf( stderr, "click (%f, %f)\n", where.x, where.y );
- surface->Click( mouseButton );
-
- //result = ActivateWindow( (WindowRef) surface->window, true );
- //assert( result == noErr );
-
- //ProcessSerialNumber psn = { 0, kCurrentProcess };
- //result = SetFrontProcess( &psn );
- //assert( result == noErr );
- } else if ( clickCount == 2 ) {
- //fprintf( stderr, "double click (%f, %f)\n", where.x, where.y );
- surface->DoubleClick( mouseButton );
- }
-
- result = noErr;
- break;
- }
-
- case kEventMouseMoved:
- case kEventMouseDragged:
- {
- surface->Move( (jint) where.x, (jint) where.y );
- result = noErr;
- //fprintf( stderr, "mousemoved (%f, %f)\n", where.x, where.y );
- break;
- }
-
- /*case kEventMouseExited:
- {
- // Move the mouse to (-1, -1) when it exits the window
- surface->Move( -1, -1 );
- result = noErr;
- fprintf( stderr, "mouse exited\n" );
- break;
- }*/
-
-
- /*case kEventMouseWheelMoved:
- {
- EventMouseWheelAxis inAxis;
- result = inEvent.GetParameter<EventMouseWheelAxis>( kEventParamMouseWheelAxis, typeMouseWheelAxis, &inAxis );
- assert( noErr == result );
-
- SInt32 inDelta;
- result = inEvent.GetParameter<SInt32>( kEventParamMouseWheelDelta, typeSInt32, &inDelta );
- assert( noErr == result );
-
- result = MouseWheelMoved( inAxis, inDelta, inKeyModifiers );
- break;
- }
- */
-
-
- // some other kind of Mouse event: This is (in my opinion) an error
- default:
- assert( false );
- break;
- }
- break;
- }
-
-
- case kEventClassKeyboard:
- switch (eventKind)
- {
- case kEventRawKeyDown:
- case kEventRawKeyRepeat:
- {
- // TODO: This breaks international input
- UniChar character = GetCharacterWithoutModifiers( event );
- surface->KeyPressed( UniCharToXWTString( character ) );
-
- result = noErr;
- break;
- }
-
- case kEventRawKeyUp:
- {
- UniChar character = GetCharacterWithoutModifiers( event );
- surface->KeyReleased( UniCharToXWTString( character ) );
-
- result = noErr;
- break;
- }
-
- case kEventRawKeyModifiersChanged:
- {
- static UInt32 previousModifiers = 0;
- UInt32 currentModifiers = GetCurrentEventKeyModifiers();
- UInt32 changedModifiers = previousModifiers ^ currentModifiers;
-
- ModifierKeyTest( surface, changedModifiers, currentModifiers, shiftKey, "shift" );
- ModifierKeyTest( surface, changedModifiers, currentModifiers, alphaLock, "caps_lock" );
- ModifierKeyTest( surface, changedModifiers, currentModifiers, controlKey, "control" );
- ModifierKeyTest( surface, changedModifiers, currentModifiers, optionKey, "alt" );
- ModifierKeyTest( surface, changedModifiers, currentModifiers, kEventKeyModifierNumLockMask, "num_lock" );
-
- previousModifiers = currentModifiers;
- result = noErr;
- break;
- }
-
- default:
- assert( false );
- break;
- }
- break;
-
- default:
- throw new java::lang::Error(JvNewStringLatin1("Unhandled Window Event"));
- }
-
- return result;