Home | History | Annotate | Download | only in Carbon
      1 /*
      2  * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14  *     its contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #ifndef __LP64__
     30 
     31 #import "HIWebView.h"
     32 
     33 #import "CarbonWindowAdapter.h"
     34 #import "HIViewAdapter.h"
     35 #import "WebHTMLViewInternal.h"
     36 #import "WebKit.h"
     37 
     38 #import <objc/objc-runtime.h>
     39 #import <WebKitSystemInterface.h>
     40 
     41 @interface NSWindow (AppKitSecretsHIWebViewKnows)
     42 - (void)_removeWindowRef;
     43 @end
     44 
     45 @interface NSView (AppKitSecretsHIWebViewKnows)
     46 - (void)_clearDirtyRectsForTree;
     47 @end
     48 
     49 extern "C" void HIWebViewRegisterClass();
     50 
     51 @interface MenuItemProxy : NSObject <NSValidatedUserInterfaceItem>
     52 {
     53     int     _tag;
     54     SEL _action;
     55 }
     56 
     57 - (id)initWithAction:(SEL)action;
     58 - (SEL)action;
     59 - (int)tag;
     60 
     61 @end
     62 
     63 @implementation MenuItemProxy
     64 
     65 - (id)initWithAction:(SEL)action
     66 {
     67     [super init];
     68     if (self == nil) return nil;
     69 
     70     _action = action;
     71 
     72     return self;
     73 }
     74 
     75 - (SEL)action
     76 {
     77        return _action;
     78 }
     79 
     80 - (int)tag
     81 {
     82     return 0;
     83 }
     84 
     85 @end
     86 
     87 struct HIWebView
     88 {
     89     HIViewRef							fViewRef;
     90 
     91     WebView*							fWebView;
     92     NSView*								fFirstResponder;
     93     CarbonWindowAdapter	*				fKitWindow;
     94     bool								fIsComposited;
     95     CFRunLoopObserverRef				fUpdateObserver;
     96 };
     97 typedef struct HIWebView HIWebView;
     98 
     99 static const OSType NSAppKitPropertyCreator = 'akit';
    100 /*
    101 These constants are not used. Commented out to make the compiler happy.
    102 static const OSType NSViewCarbonControlViewPropertyTag = 'view';
    103 static const OSType NSViewCarbonControlAutodisplayPropertyTag = 'autd';
    104 static const OSType NSViewCarbonControlFirstResponderViewPropertyTag = 'frvw';
    105 */
    106 static const OSType NSCarbonWindowPropertyTag = 'win ';
    107 
    108 #ifdef BUILDING_ON_TIGER
    109 const int typeByteCount = typeSInt32;
    110 #endif
    111 
    112 static SEL _NSSelectorForHICommand( const HICommand* hiCommand );
    113 
    114 static const EventTypeSpec kEvents[] = {
    115 	{ kEventClassHIObject, kEventHIObjectConstruct },
    116 	{ kEventClassHIObject, kEventHIObjectDestruct },
    117 
    118 	{ kEventClassMouse, kEventMouseUp },
    119 	{ kEventClassMouse, kEventMouseMoved },
    120 	{ kEventClassMouse, kEventMouseDragged },
    121 	{ kEventClassMouse, kEventMouseWheelMoved },
    122 
    123 	{ kEventClassKeyboard, kEventRawKeyDown },
    124 	{ kEventClassKeyboard, kEventRawKeyRepeat },
    125 
    126 	{ kEventClassCommand, kEventCommandProcess },
    127 	{ kEventClassCommand, kEventCommandUpdateStatus },
    128 
    129 	{ kEventClassControl, kEventControlInitialize },
    130 	{ kEventClassControl, kEventControlDraw },
    131 	{ kEventClassControl, kEventControlHitTest },
    132 	{ kEventClassControl, kEventControlGetPartRegion },
    133 	{ kEventClassControl, kEventControlGetData },
    134 	{ kEventClassControl, kEventControlBoundsChanged },
    135 	{ kEventClassControl, kEventControlActivate },
    136 	{ kEventClassControl, kEventControlDeactivate },
    137 	{ kEventClassControl, kEventControlOwningWindowChanged },
    138 	{ kEventClassControl, kEventControlClick },
    139 	{ kEventClassControl, kEventControlContextualMenuClick },
    140 	{ kEventClassControl, kEventControlSetFocusPart }
    141 };
    142 
    143 #define kHIViewBaseClassID		CFSTR( "com.apple.hiview" )
    144 #define kHIWebViewClassID		CFSTR( "com.apple.HIWebView" )
    145 
    146 static HIWebView*		HIWebViewConstructor( HIViewRef inView );
    147 static void				HIWebViewDestructor( HIWebView* view );
    148 
    149 static OSStatus			HIWebViewEventHandler(
    150 								EventHandlerCallRef	inCallRef,
    151 								EventRef			inEvent,
    152 								void *				inUserData );
    153 
    154 static UInt32			GetBehaviors();
    155 static ControlKind		GetKind();
    156 static void				Draw( HIWebView* inView, RgnHandle limitRgn, CGContextRef inContext );
    157 static ControlPartCode	HitTest( HIWebView* view, const HIPoint* where );
    158 static OSStatus			GetRegion( HIWebView* view, ControlPartCode inPart, RgnHandle outRgn );
    159 static void				BoundsChanged(
    160 								HIWebView*			inView,
    161 								UInt32				inOptions,
    162 								const HIRect*		inOriginalBounds,
    163 								const HIRect*		inCurrentBounds );
    164 static void				OwningWindowChanged(
    165 								HIWebView*			view,
    166 								WindowRef			oldWindow,
    167 								WindowRef			newWindow );
    168 static void				ActiveStateChanged( HIWebView* view );
    169 
    170 static OSStatus			Click( HIWebView* inView, EventRef inEvent );
    171 static OSStatus			ContextMenuClick( HIWebView* inView, EventRef inEvent );
    172 static OSStatus			MouseUp( HIWebView* inView, EventRef inEvent );
    173 static OSStatus			MouseMoved( HIWebView* inView, EventRef inEvent );
    174 static OSStatus			MouseDragged( HIWebView* inView, EventRef inEvent );
    175 static OSStatus			MouseWheelMoved( HIWebView* inView, EventRef inEvent );
    176 
    177 static OSStatus			ProcessCommand( HIWebView* inView, const HICommand* inCommand );
    178 static OSStatus			UpdateCommandStatus( HIWebView* inView, const HICommand* inCommand );
    179 
    180 static OSStatus			SetFocusPart(
    181 								HIWebView*				view,
    182 								ControlPartCode 		desiredFocus,
    183 								RgnHandle 				invalidRgn,
    184 								Boolean 				focusEverything,
    185 								ControlPartCode* 		actualFocus );
    186 static NSView*			AdvanceFocus( HIWebView* view, bool forward );
    187 static void				RelinquishFocus( HIWebView* view, bool inAutodisplay );
    188 
    189 static WindowRef		GetWindowRef( HIWebView* inView );
    190 static void				SyncFrame( HIWebView* inView );
    191 
    192 static OSStatus			WindowHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData );
    193 
    194 static void				StartUpdateObserver( HIWebView* view );
    195 static void				StopUpdateObserver( HIWebView* view );
    196 
    197 static inline void HIRectToQDRect( const HIRect* inRect, Rect* outRect )
    198 {
    199     outRect->top = (SInt16)CGRectGetMinY( *inRect );
    200     outRect->left = (SInt16)CGRectGetMinX( *inRect );
    201     outRect->bottom = (SInt16)CGRectGetMaxY( *inRect );
    202     outRect->right = (SInt16)CGRectGetMaxX( *inRect );
    203 }
    204 
    205 //----------------------------------------------------------------------------------
    206 // HIWebViewCreate
    207 //----------------------------------------------------------------------------------
    208 //
    209 OSStatus
    210 HIWebViewCreate(HIViewRef* outControl)
    211 {
    212     HIWebViewRegisterClass();
    213     return HIObjectCreate(kHIWebViewClassID, NULL, (HIObjectRef*)outControl);
    214 }
    215 
    216 //----------------------------------------------------------------------------------
    217 // HIWebViewGetWebView
    218 //----------------------------------------------------------------------------------
    219 //
    220 WebView*
    221 HIWebViewGetWebView( HIViewRef inView )
    222 {
    223 	HIWebView* 	view = (HIWebView*)HIObjectDynamicCast( (HIObjectRef)inView, kHIWebViewClassID );
    224 	WebView*			result = NULL;
    225 
    226 	if ( view )
    227 		result = view->fWebView;
    228 
    229 	return result;
    230 }
    231 
    232 //----------------------------------------------------------------------------------
    233 // HIWebViewConstructor
    234 //----------------------------------------------------------------------------------
    235 //
    236 
    237 static HIWebView*
    238 HIWebViewConstructor( HIViewRef inView )
    239 {
    240 	HIWebView*		view = (HIWebView*)malloc( sizeof( HIWebView ) );
    241 
    242 	if ( view )
    243 	{
    244 		NSRect		frame = { { 0, 0 }, { 400, 400  } };
    245 
    246 		view->fViewRef = inView;
    247 
    248                 WebView *webView = [[WebView alloc] initWithFrame: frame];
    249                 CFRetain(webView);
    250                 [webView release];
    251 		view->fWebView = webView;
    252 		[HIViewAdapter bindHIViewToNSView:inView nsView:view->fWebView];
    253 
    254 		view->fFirstResponder = NULL;
    255 		view->fKitWindow = NULL;
    256         view->fIsComposited = false;
    257         view->fUpdateObserver = NULL;
    258 	}
    259 
    260 	return view;
    261 }
    262 
    263 //----------------------------------------------------------------------------------
    264 // HIWebViewDestructor
    265 //----------------------------------------------------------------------------------
    266 //
    267 static void
    268 HIWebViewDestructor( HIWebView* inView )
    269 {
    270     [HIViewAdapter unbindNSView:inView->fWebView];
    271     CFRelease(inView->fWebView);
    272 
    273     free(inView);
    274 }
    275 
    276 //----------------------------------------------------------------------------------
    277 // HIWebViewRegisterClass
    278 //----------------------------------------------------------------------------------
    279 //
    280 void
    281 HIWebViewRegisterClass()
    282 {
    283 	static bool sRegistered;
    284 
    285 	if ( !sRegistered )
    286 	{
    287 		HIObjectRegisterSubclass( kHIWebViewClassID, kHIViewBaseClassID, 0, HIWebViewEventHandler,
    288 			GetEventTypeCount( kEvents ), kEvents, 0, NULL );
    289 		sRegistered = true;
    290 	}
    291 }
    292 
    293 //----------------------------------------------------------------------------------
    294 // GetBehaviors
    295 //----------------------------------------------------------------------------------
    296 //
    297 static UInt32
    298 GetBehaviors()
    299 {
    300 	return kControlSupportsDataAccess | kControlSupportsGetRegion | kControlGetsFocusOnClick;
    301 }
    302 
    303 //----------------------------------------------------------------------------------
    304 // Draw
    305 //----------------------------------------------------------------------------------
    306 //
    307 static void
    308 Draw( HIWebView* inView, RgnHandle limitRgn, CGContextRef inContext )
    309 {
    310 	HIRect				bounds;
    311 	Rect				drawRect;
    312 	HIRect				hiRect;
    313 	bool				createdContext = false;
    314 
    315     if (!inView->fIsComposited)
    316     {
    317         GrafPtr port;
    318         Rect portRect;
    319 
    320         GetPort( &port );
    321         GetPortBounds( port, &portRect );
    322         CreateCGContextForPort( port, &inContext );
    323         SyncCGContextOriginWithPort( inContext, port );
    324         CGContextTranslateCTM( inContext, 0, (portRect.bottom - portRect.top) );
    325         CGContextScaleCTM( inContext, 1, -1 );
    326         createdContext = true;
    327     }
    328 
    329 	HIViewGetBounds( inView->fViewRef, &bounds );
    330 
    331     CGContextRef savedContext = WKNSWindowOverrideCGContext(inView->fKitWindow, inContext);
    332     [NSGraphicsContext setCurrentContext:[inView->fKitWindow graphicsContext]];
    333 
    334 	GetRegionBounds( limitRgn, &drawRect );
    335 
    336     if ( !inView->fIsComposited )
    337         OffsetRect( &drawRect, (SInt16)-bounds.origin.x, (SInt16)-bounds.origin.y );
    338 
    339 	hiRect.origin.x = drawRect.left;
    340 	hiRect.origin.y = bounds.size.height - drawRect.bottom; // flip y
    341 	hiRect.size.width = drawRect.right - drawRect.left;
    342 	hiRect.size.height = drawRect.bottom - drawRect.top;
    343 
    344 //    printf( "Drawing: drawRect is (%g %g) (%g %g)\n", hiRect.origin.x, hiRect.origin.y,
    345 //            hiRect.size.width, hiRect.size.height );
    346 
    347     // FIXME: We need to do layout before Carbon has decided what region needs drawn.
    348     // In Cocoa we make sure to do layout and invalidate any new regions before draw, so everything
    349     // can be drawn in one pass. Doing a layout here will cause new regions to be invalidated, but they
    350     // will not all be drawn in this pass since we already have a fixed rect we are going to display.
    351 
    352     NSView <WebDocumentView> *documentView = [[[inView->fWebView mainFrame] frameView] documentView];
    353     if ([documentView isKindOfClass:[WebHTMLView class]])
    354         [(WebHTMLView *)documentView _web_layoutIfNeededRecursive];
    355 
    356     if ( inView->fIsComposited )
    357         [inView->fWebView displayIfNeededInRect: *(NSRect*)&hiRect];
    358     else
    359         [inView->fWebView displayRect:*(NSRect*)&hiRect];
    360 
    361     WKNSWindowRestoreCGContext(inView->fKitWindow, savedContext);
    362 
    363     if ( !inView->fIsComposited )
    364     {
    365         HIViewRef      view;
    366         HIViewFindByID( HIViewGetRoot( GetControlOwner( inView->fViewRef ) ), kHIViewWindowGrowBoxID, &view );
    367         if ( view )
    368         {
    369             HIRect     frame;
    370 
    371             HIViewGetBounds( view, &frame );
    372             HIViewConvertRect( &frame, view, NULL );
    373 
    374             hiRect.origin.x = drawRect.left;
    375             hiRect.origin.y = drawRect.top;
    376             hiRect.size.width = drawRect.right - drawRect.left;
    377             hiRect.size.height = drawRect.bottom - drawRect.top;
    378 
    379             HIViewConvertRect( &hiRect, inView->fViewRef, NULL );
    380 
    381             if ( CGRectIntersectsRect( frame, hiRect ) )
    382                 HIViewSetNeedsDisplay( view, true );
    383         }
    384      }
    385 
    386     if ( createdContext )
    387     {
    388         CGContextSynchronize( inContext );
    389         CGContextRelease( inContext );
    390     }
    391 }
    392 
    393 //----------------------------------------------------------------------------------
    394 // HitTest
    395 //----------------------------------------------------------------------------------
    396 //
    397 static ControlPartCode
    398 HitTest( HIWebView* view, const HIPoint* where )
    399 {
    400 	HIRect		bounds;
    401 
    402 	HIViewGetBounds( view->fViewRef, &bounds );
    403 
    404 	if ( CGRectContainsPoint( bounds, *where ) )
    405 		return 1;
    406 	else
    407 		return kControlNoPart;
    408 }
    409 
    410 //----------------------------------------------------------------------------------
    411 // GetRegion
    412 //----------------------------------------------------------------------------------
    413 //
    414 static OSStatus
    415 GetRegion(
    416 	HIWebView*			inView,
    417 	ControlPartCode		inPart,
    418 	RgnHandle			outRgn )
    419 {
    420 	OSStatus	 err = eventNotHandledErr;
    421 
    422 	if ( inPart == -3 ) // kControlOpaqueMetaPart:
    423 	{
    424 		if ( [inView->fWebView isOpaque] )
    425 		{
    426 			HIRect	bounds;
    427 			Rect	temp;
    428 
    429 			HIViewGetBounds( inView->fViewRef, &bounds );
    430 
    431 			temp.top = (SInt16)bounds.origin.y;
    432 			temp.left = (SInt16)bounds.origin.x;
    433 			temp.bottom = (SInt16)CGRectGetMaxY( bounds );
    434 			temp.right = (SInt16)CGRectGetMaxX( bounds );
    435 
    436 			RectRgn( outRgn, &temp );
    437 			err = noErr;
    438 		}
    439 	}
    440 
    441 	return err;
    442 }
    443 
    444 static WindowRef
    445 GetWindowRef( HIWebView* inView )
    446 {
    447        return GetControlOwner( inView->fViewRef );
    448 }
    449 
    450 //----------------------------------------------------------------------------------
    451 // Click
    452 //----------------------------------------------------------------------------------
    453 //
    454 static OSStatus
    455 Click(HIWebView* inView, EventRef inEvent)
    456 {
    457     NSEvent *kitEvent = WKCreateNSEventWithCarbonClickEvent(inEvent, GetWindowRef(inView));
    458 
    459     if (!inView->fIsComposited)
    460         StartUpdateObserver(inView);
    461 
    462     [inView->fKitWindow sendEvent:kitEvent];
    463 
    464     if (!inView->fIsComposited)
    465         StopUpdateObserver(inView);
    466 
    467     [kitEvent release];
    468 
    469     return noErr;
    470 }
    471 
    472 //----------------------------------------------------------------------------------
    473 // MouseUp
    474 //----------------------------------------------------------------------------------
    475 //
    476 static OSStatus
    477 MouseUp( HIWebView* inView, EventRef inEvent )
    478 {
    479 	NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
    480 
    481     [inView->fKitWindow sendEvent:kitEvent];
    482 
    483     [kitEvent release];
    484 
    485 	return noErr;
    486 }
    487 
    488 //----------------------------------------------------------------------------------
    489 // MouseMoved
    490 //----------------------------------------------------------------------------------
    491 //
    492 static OSStatus
    493 MouseMoved( HIWebView* inView, EventRef inEvent )
    494 {
    495     NSEvent *kitEvent = WKCreateNSEventWithCarbonMouseMoveEvent(inEvent, inView->fKitWindow);
    496     [inView->fKitWindow sendEvent:kitEvent];
    497 	[kitEvent release];
    498 
    499 	return noErr;
    500 }
    501 
    502 //----------------------------------------------------------------------------------
    503 // MouseDragged
    504 //----------------------------------------------------------------------------------
    505 //
    506 static OSStatus
    507 MouseDragged( HIWebView* inView, EventRef inEvent )
    508 {
    509 	NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
    510 
    511     [inView->fKitWindow sendEvent:kitEvent];
    512 
    513 	[kitEvent release];
    514 
    515 	return noErr;
    516 }
    517 
    518 //----------------------------------------------------------------------------------
    519 // MouseDragged
    520 //----------------------------------------------------------------------------------
    521 //
    522 static OSStatus
    523 MouseWheelMoved( HIWebView* inView, EventRef inEvent )
    524 {
    525 	NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
    526 
    527     [inView->fKitWindow sendEvent:kitEvent];
    528 
    529 	[kitEvent release];
    530 
    531 	return noErr;
    532 }
    533 
    534 //----------------------------------------------------------------------------------
    535 // ContextMenuClick
    536 //----------------------------------------------------------------------------------
    537 //
    538 static OSStatus
    539 ContextMenuClick( HIWebView* inView, EventRef inEvent )
    540 {
    541     NSView *webView = inView->fWebView;
    542     NSWindow *window = [webView window];
    543 
    544     // Get the point out of the event.
    545     HIPoint point;
    546     GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(point), NULL, &point);
    547     HIViewConvertPoint(&point, inView->fViewRef, NULL);
    548 
    549     // Flip the Y coordinate, since Carbon is flipped relative to the AppKit.
    550     NSPoint location = NSMakePoint(point.x, [window frame].size.height - point.y);
    551 
    552     // Make up an event with the point and send it to the window.
    553     NSEvent *kitEvent = [NSEvent mouseEventWithType:NSRightMouseDown
    554                                            location:location
    555                                       modifierFlags:0
    556                                           timestamp:GetEventTime(inEvent)
    557                                        windowNumber:[window windowNumber]
    558                                             context:0
    559                                         eventNumber:0
    560                                          clickCount:1
    561                                            pressure:0];
    562     [inView->fKitWindow sendEvent:kitEvent];
    563     return noErr;
    564 }
    565 
    566 //----------------------------------------------------------------------------------
    567 // GetKind
    568 //----------------------------------------------------------------------------------
    569 //
    570 static ControlKind
    571 GetKind()
    572 {
    573 	const ControlKind kMyKind = { 'appl', 'wbvw' };
    574 
    575 	return kMyKind;
    576 }
    577 
    578 //----------------------------------------------------------------------------------
    579 // BoundsChanged
    580 //----------------------------------------------------------------------------------
    581 //
    582 static void
    583 BoundsChanged(
    584 	HIWebView*			inView,
    585 	UInt32				inOptions,
    586 	const HIRect*		inOriginalBounds,
    587 	const HIRect*		inCurrentBounds )
    588 {
    589 	if ( inView->fWebView )
    590 	{
    591 		SyncFrame( inView );
    592 	}
    593 }
    594 
    595 //----------------------------------------------------------------------------------
    596 // OwningWindowChanged
    597 //----------------------------------------------------------------------------------
    598 //
    599 static void
    600 OwningWindowChanged(
    601 	HIWebView*			view,
    602 	WindowRef			oldWindow,
    603 	WindowRef			newWindow )
    604 {
    605     if ( newWindow ){
    606         WindowAttributes	attrs;
    607 
    608         OSStatus err = GetWindowProperty(newWindow, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &view->fKitWindow);
    609         if ( err != noErr )
    610         {
    611             const EventTypeSpec kWindowEvents[] = {
    612             { kEventClassWindow, kEventWindowClosed },
    613             { kEventClassMouse, kEventMouseMoved },
    614             { kEventClassMouse, kEventMouseUp },
    615             { kEventClassMouse, kEventMouseDragged },
    616             { kEventClassMouse, kEventMouseWheelMoved },
    617             { kEventClassKeyboard, kEventRawKeyDown },
    618             { kEventClassKeyboard, kEventRawKeyRepeat },
    619             { kEventClassKeyboard, kEventRawKeyUp },
    620             { kEventClassControl, kEventControlClick },
    621             };
    622 
    623             view->fKitWindow = [[CarbonWindowAdapter alloc] initWithCarbonWindowRef: newWindow takingOwnership: NO disableOrdering:NO carbon:YES];
    624             SetWindowProperty(newWindow, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), &view->fKitWindow);
    625 
    626             InstallWindowEventHandler( newWindow, WindowHandler, GetEventTypeCount( kWindowEvents ), kWindowEvents, newWindow, NULL );
    627         }
    628 
    629         [[view->fKitWindow contentView] addSubview:view->fWebView];
    630 
    631         GetWindowAttributes( newWindow, &attrs );
    632         view->fIsComposited = ( ( attrs & kWindowCompositingAttribute ) != 0 );
    633 
    634         SyncFrame( view );
    635     }
    636     else
    637     {
    638         // Be sure to detach the cocoa view, too.
    639         if ( view->fWebView )
    640             [view->fWebView removeFromSuperview];
    641 
    642         view->fKitWindow = NULL; // break the ties that bind
    643     }
    644 }
    645 
    646 //-------------------------------------------------------------------------------------
    647 //	WindowHandler
    648 //-------------------------------------------------------------------------------------
    649 //	Redirect mouse events to the views beneath them. This is required for WebKit to work
    650 // 	properly. We install it once per window. We also tap into window close to release
    651 //	the NSWindow that shadows our Carbon window.
    652 //
    653 static OSStatus
    654 WindowHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
    655 {
    656 	WindowRef	window = (WindowRef)inUserData;
    657 	OSStatus	result = eventNotHandledErr;
    658 
    659     switch( GetEventClass( inEvent ) )
    660     {
    661     	case kEventClassControl:
    662             {
    663             switch( GetEventKind( inEvent ) )
    664             {
    665                 case kEventControlClick:
    666                     {
    667                         CarbonWindowAdapter *kitWindow;
    668                         OSStatus err;
    669 
    670                         err = GetWindowProperty( window, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &kitWindow);
    671 
    672                         // We must be outside the HIWebView, relinquish focus.
    673                         [kitWindow relinquishFocus];
    674                     }
    675                     break;
    676                 }
    677             }
    678             break;
    679 
    680     	case kEventClassKeyboard:
    681     		{
    682                 NSWindow*		kitWindow;
    683                 OSStatus		err;
    684    				NSEvent*		kitEvent;
    685 
    686    				// if the first responder in the kit window is something other than the
    687    				// window, we assume a subview of the webview is focused. we must send
    688    				// the event to the window so that it goes through the kit's normal TSM
    689    				// logic, and -- more importantly -- allows any delegates associated
    690    				// with the first responder to have a chance at the event.
    691 
    692 				err = GetWindowProperty( window, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &kitWindow);
    693 				if ( err == noErr )
    694 				{
    695 					NSResponder* responder = [kitWindow firstResponder];
    696 					if ( responder != kitWindow )
    697 					{
    698                         kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
    699 
    700 						[kitWindow sendEvent:kitEvent];
    701 						[kitEvent release];
    702 
    703 						result = noErr;
    704 					}
    705 				}
    706     		}
    707     		break;
    708 
    709         case kEventClassWindow:
    710             {
    711                 NSWindow*	kitWindow;
    712                 OSStatus	err;
    713 
    714                 err = GetWindowProperty( window, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &kitWindow);
    715                 if ( err == noErr )
    716                 {
    717                     [kitWindow _removeWindowRef];
    718                     [kitWindow close];
    719                 }
    720 
    721                 result = noErr;
    722             }
    723             break;
    724 
    725         case kEventClassMouse:
    726             switch (GetEventKind(inEvent))
    727             {
    728                 case kEventMouseMoved:
    729                     {
    730                         Point where;
    731                         GetEventParameter(inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &where);
    732 
    733                         WindowRef temp;
    734                         FindWindow(where, &temp);
    735                         if (temp == window)
    736                         {
    737                             Rect bounds;
    738                             GetWindowBounds(window, kWindowStructureRgn, &bounds);
    739                             where.h -= bounds.left;
    740                             where.v -= bounds.top;
    741                             SetEventParameter(inEvent, kEventParamWindowRef, typeWindowRef, sizeof(WindowRef), &window);
    742                             SetEventParameter(inEvent, kEventParamWindowMouseLocation, typeQDPoint, sizeof(Point), &where);
    743 
    744                             OSStatus err = noErr;
    745                             HIViewRef view = NULL;
    746 
    747                             err = HIViewGetViewForMouseEvent(HIViewGetRoot(window), inEvent, &view);
    748                             if (err == noErr && view && HIObjectIsOfClass((HIObjectRef)view, kHIWebViewClassID))
    749                                 result = SendEventToEventTargetWithOptions(inEvent, HIObjectGetEventTarget((HIObjectRef)view), kEventTargetDontPropagate);
    750                         }
    751                     }
    752                     break;
    753 
    754                 case kEventMouseUp:
    755                 case kEventMouseDragged:
    756                 case kEventMouseWheelMoved:
    757                     {
    758                         OSStatus err = noErr;
    759                         HIViewRef view = NULL;
    760 
    761                         err = HIViewGetViewForMouseEvent(HIViewGetRoot(window), inEvent, &view);
    762                         if (err == noErr && view && HIObjectIsOfClass((HIObjectRef)view, kHIWebViewClassID))
    763                             result = SendEventToEventTargetWithOptions(inEvent, HIObjectGetEventTarget((HIObjectRef)view), kEventTargetDontPropagate);
    764                     }
    765                     break;
    766             }
    767             break;
    768     }
    769 
    770 	return result;
    771 }
    772 
    773 
    774 //----------------------------------------------------------------------------------
    775 // SyncFrame
    776 //----------------------------------------------------------------------------------
    777 //
    778 static void
    779 SyncFrame( HIWebView* inView )
    780 {
    781 	HIViewRef	parent = HIViewGetSuperview( inView->fViewRef );
    782 
    783 	if ( parent )
    784 	{
    785         if ( inView->fIsComposited )
    786         {
    787             HIRect		frame;
    788             HIRect		parentBounds;
    789             NSPoint		origin;
    790 
    791             HIViewGetFrame( inView->fViewRef, &frame );
    792             HIViewGetBounds( parent, &parentBounds );
    793 
    794             origin.x = frame.origin.x;
    795             origin.y = parentBounds.size.height - CGRectGetMaxY( frame );
    796 //    printf( "syncing to (%g %g) (%g %g)\n", origin.x, origin.y,
    797 //            frame.size.width, frame.size.height );
    798             [inView->fWebView setFrameOrigin: origin];
    799             [inView->fWebView setFrameSize: *(NSSize*)&frame.size];
    800         }
    801         else
    802         {
    803             GrafPtr			port = GetWindowPort( GetControlOwner( inView->fViewRef ) );
    804             PixMapHandle	portPix = GetPortPixMap( port );
    805             Rect			bounds;
    806             HIRect			rootFrame;
    807             HIRect			frame;
    808 
    809             GetControlBounds( inView->fViewRef, &bounds );
    810             OffsetRect( &bounds, -(**portPix).bounds.left, -(**portPix).bounds.top );
    811 
    812 //            printf( "control lives at %d %d %d %d in window-coords\n", bounds.top, bounds.left,
    813 //                bounds.bottom, bounds.right );
    814 
    815             HIViewGetFrame( HIViewGetRoot( GetControlOwner( inView->fViewRef ) ), &rootFrame );
    816 
    817             frame.origin.x = bounds.left;
    818             frame.origin.y = rootFrame.size.height - bounds.bottom;
    819             frame.size.width = bounds.right - bounds.left;
    820             frame.size.height = bounds.bottom - bounds.top;
    821 
    822 //            printf( "   before frame convert (%g %g) (%g %g)\n", frame.origin.x, frame.origin.y,
    823 //                frame.size.width, frame.size.height );
    824 
    825             [inView->fWebView convertRect:*(NSRect*)&frame fromView:nil];
    826 
    827 //            printf( "   moving web view to (%g %g) (%g %g)\n", frame.origin.x, frame.origin.y,
    828 //                frame.size.width, frame.size.height );
    829 
    830             [inView->fWebView setFrameOrigin: *(NSPoint*)&frame.origin];
    831             [inView->fWebView setFrameSize: *(NSSize*)&frame.size];
    832         }
    833     }
    834 }
    835 
    836 //----------------------------------------------------------------------------------
    837 // SetFocusPart
    838 //----------------------------------------------------------------------------------
    839 //
    840 static OSStatus
    841 SetFocusPart(
    842 	HIWebView*				view,
    843 	ControlPartCode 		desiredFocus,
    844 	RgnHandle 				invalidRgn,
    845 	Boolean 				focusEverything,
    846 	ControlPartCode* 		actualFocus )
    847 {
    848     NSView *	freshlyMadeFirstResponderView;
    849     SInt32 		partCodeToReturn;
    850 
    851     // Do what Carbon is telling us to do.
    852     if ( desiredFocus == kControlFocusNoPart )
    853 	{
    854         // Relinquish the keyboard focus.
    855         RelinquishFocus( view, true ); //(autodisplay ? YES : NO));
    856         freshlyMadeFirstResponderView = nil;
    857         partCodeToReturn = kControlFocusNoPart;
    858 		//NSLog(@"Relinquished the key focus because we have no choice.");
    859     }
    860 	else if ( desiredFocus == kControlFocusNextPart || desiredFocus == kControlFocusPrevPart )
    861 	{
    862         BOOL goForward = (desiredFocus == kControlFocusNextPart );
    863 
    864         // Advance the keyboard focus, maybe right off of this view.  Maybe a subview of this one already has the keyboard focus, maybe not.
    865         freshlyMadeFirstResponderView = AdvanceFocus( view, goForward );
    866         if (freshlyMadeFirstResponderView)
    867             partCodeToReturn = desiredFocus;
    868         else
    869             partCodeToReturn = kControlFocusNoPart;
    870         //NSLog(freshlyMadeFirstResponderView ? @"Advanced the key focus." : @"Relinquished the key focus.");
    871     }
    872 	else
    873 	{
    874 		// What's this?
    875                 if (desiredFocus != kControlIndicatorPart) {
    876                     check(false);
    877                 }
    878 		freshlyMadeFirstResponderView = nil;
    879 		partCodeToReturn = desiredFocus;
    880     }
    881 
    882 	view->fFirstResponder = freshlyMadeFirstResponderView;
    883 
    884 	*actualFocus = partCodeToReturn;
    885 
    886 	// Done.
    887 	return noErr;
    888 }
    889 
    890 //----------------------------------------------------------------------------------
    891 // AdvanceFocus
    892 //----------------------------------------------------------------------------------
    893 //
    894 static NSView*
    895 AdvanceFocus( HIWebView* view, bool forward )
    896 {
    897     NSResponder*		oldFirstResponder;
    898     NSView*				currentKeyView;
    899     NSView*				viewWeMadeFirstResponder;
    900 
    901     //	Focus on some part (subview) of this control (view).  Maybe
    902 	//	a subview of this one already has the keyboard focus, maybe not.
    903 
    904 	oldFirstResponder = [view->fKitWindow firstResponder];
    905 
    906 	// If we tab out of our NSView, it will no longer be the responder
    907 	// when we get here. We'll try this trick for now. We might need to
    908 	// tag the view appropriately.
    909 
    910 	if ( view->fFirstResponder && ( (NSResponder*)view->fFirstResponder != oldFirstResponder ) )
    911 	{
    912 		return NULL;
    913 	}
    914 
    915 	if ( [oldFirstResponder isKindOfClass:[NSView class]] )
    916 	{
    917 		NSView*		tentativeNewKeyView;
    918 
    919         // Some view in this window already has the keyboard focus.  It better at least be a subview of this one.
    920         NSView*	oldFirstResponderView = (NSView *)oldFirstResponder;
    921         check( [oldFirstResponderView isDescendantOf:view->fWebView] );
    922 
    923 		if ( oldFirstResponderView != view->fFirstResponder
    924 			&& ![oldFirstResponderView isDescendantOf:view->fFirstResponder] )
    925 		{
    926             // Despite our efforts to record what view we made the first responder
    927 			// (for use in the next paragraph) we couldn't keep up because the user
    928 			// has clicked in a text field to make it the key focus, instead of using
    929 			// the tab key.  Find a control on which it's reasonable to invoke
    930 			// -[NSView nextValidKeyView], taking into account the fact that
    931 			// NSTextFields always pass on first-respondership to a temporarily-
    932 			// contained NSTextView.
    933 
    934 			NSView *viewBeingTested;
    935 			currentKeyView = oldFirstResponderView;
    936 			viewBeingTested = currentKeyView;
    937 			while ( viewBeingTested != view->fWebView )
    938 			{
    939 				if ( [viewBeingTested isKindOfClass:[NSTextField class]] )
    940 				{
    941 					currentKeyView = viewBeingTested;
    942 					break;
    943 				}
    944 				else
    945 				{
    946 					viewBeingTested = [viewBeingTested superview];
    947 				}
    948 			}
    949 		}
    950 		else
    951 		{
    952 			// We recorded which view we made into the first responder the
    953 			// last time the user hit the tab key, and nothing has invalidated
    954 			// our recorded value since.
    955 
    956 			currentKeyView = view->fFirstResponder;
    957 		}
    958 
    959         // Try to move on to the next or previous key view.  We use the laboriously
    960 		// recorded/figured currentKeyView instead of just oldFirstResponder as the
    961 		// jumping-off-point when searching for the next valid key view.  This is so
    962 		// we don't get fooled if we recently made some view the first responder, but
    963 		// it passed on first-responder-ness to some temporary subview.
    964 
    965         // You can't put normal views in a window with Carbon-control-wrapped views.
    966 		// Stuff like this would break.  M.P. Notice - 12/2/00
    967 
    968         tentativeNewKeyView = forward ? [currentKeyView nextValidKeyView] : [currentKeyView previousValidKeyView];
    969         if ( tentativeNewKeyView && [tentativeNewKeyView isDescendantOf:view->fWebView] )
    970 		{
    971             // The user has tabbed to another subview of this control view.  Change the keyboard focus.
    972             //NSLog(@"Tabbed to the next or previous key view.");
    973 
    974             [view->fKitWindow makeFirstResponder:tentativeNewKeyView];
    975             viewWeMadeFirstResponder = tentativeNewKeyView;
    976         }
    977 		else
    978 		{
    979             // The user has tabbed past the subviews of this control view.  The window is the first responder now.
    980             //NSLog(@"Tabbed past the first or last key view.");
    981             [view->fKitWindow makeFirstResponder:view->fKitWindow];
    982             viewWeMadeFirstResponder = nil;
    983         }
    984     }
    985 	else
    986 	{
    987         // No view in this window has the keyboard focus.  This view should
    988 		// try to select one of its key subviews.  We're not interested in
    989 		// the subviews of sibling views here.
    990 
    991 		//NSLog(@"No keyboard focus in window. Attempting to set...");
    992 
    993 		NSView *tentativeNewKeyView;
    994 		check(oldFirstResponder==fKitWindow);
    995 		if ( [view->fWebView acceptsFirstResponder] )
    996 			tentativeNewKeyView = view->fWebView;
    997 		else
    998 			tentativeNewKeyView = [view->fWebView nextValidKeyView];
    999         if ( tentativeNewKeyView && [tentativeNewKeyView isDescendantOf:view->fWebView] )
   1000 		{
   1001             // This control view has at least one subview that can take the keyboard focus.
   1002             if ( !forward )
   1003 			{
   1004                 // The user has tabbed into this control view backwards.  Find
   1005 				// and select the last subview of this one that can take the
   1006 				// keyboard focus.  Watch out for loops of valid key views.
   1007 
   1008                 NSView *firstTentativeNewKeyView = tentativeNewKeyView;
   1009                 NSView *nextTentativeNewKeyView = [tentativeNewKeyView nextValidKeyView];
   1010                 while ( nextTentativeNewKeyView
   1011 						&& [nextTentativeNewKeyView isDescendantOf:view->fWebView]
   1012 						&& nextTentativeNewKeyView!=firstTentativeNewKeyView)
   1013 				{
   1014                     tentativeNewKeyView = nextTentativeNewKeyView;
   1015                     nextTentativeNewKeyView = [tentativeNewKeyView nextValidKeyView];
   1016                 }
   1017 
   1018             }
   1019 
   1020             // Set the keyboard focus.
   1021             //NSLog(@"Tabbed into the first or last key view.");
   1022             [view->fKitWindow makeFirstResponder:tentativeNewKeyView];
   1023             viewWeMadeFirstResponder = tentativeNewKeyView;
   1024         }
   1025 		else
   1026 		{
   1027             // This control view has no subviews that can take the keyboard focus.
   1028             //NSLog(@"Can't tab into this view.");
   1029             viewWeMadeFirstResponder = nil;
   1030         }
   1031     }
   1032 
   1033     // Done.
   1034     return viewWeMadeFirstResponder;
   1035 }
   1036 
   1037 
   1038 //----------------------------------------------------------------------------------
   1039 // RelinquishFocus
   1040 //----------------------------------------------------------------------------------
   1041 //
   1042 static void
   1043 RelinquishFocus( HIWebView* view, bool inAutodisplay )
   1044 {
   1045     NSResponder*  firstResponder;
   1046 
   1047     // Apparently Carbon thinks that some subview of this control view has the keyboard focus,
   1048 	// or we wouldn't be being asked to relinquish focus.
   1049 
   1050 	firstResponder = [view->fKitWindow firstResponder];
   1051 	if ( [firstResponder isKindOfClass:[NSView class]] )
   1052 	{
   1053 		// Some subview of this control view really is the first responder right now.
   1054 		check( [(NSView *)firstResponder isDescendantOf:view->fWebView] );
   1055 
   1056 		// Make the window the first responder, so that no view is the key view.
   1057         [view->fKitWindow makeFirstResponder:view->fKitWindow];
   1058 
   1059 		// 	If this control is not allowed to do autodisplay, don't let
   1060 		//	it autodisplay any just-changed focus rings or text on the
   1061 		//	next go around the event loop. I'm probably clearing more
   1062 		//	dirty rects than I have to, but it doesn't seem to hurt in
   1063 		//	the print panel accessory view case, and I don't have time
   1064 		//	to figure out exactly what -[NSCell _setKeyboardFocusRingNeedsDisplay]
   1065 		//	is doing when invoked indirectly from -makeFirstResponder up above.  M.P. Notice - 12/4/00
   1066 
   1067 		if ( !inAutodisplay )
   1068 			[[view->fWebView opaqueAncestor] _clearDirtyRectsForTree];
   1069     }
   1070 	else
   1071 	{
   1072 		//  The Cocoa first responder does not correspond to the Carbon
   1073 		//	control that has the keyboard focus.  This can happen when
   1074 		//	you've closed a dialog by hitting return in an NSTextView
   1075 		//	that's a subview of this one; Cocoa closed the window, and
   1076 		//	now Carbon is telling this control to relinquish the focus
   1077 		//	as it's being disposed.  There's nothing to do.
   1078 
   1079 		check(firstResponder==window);
   1080 	}
   1081 }
   1082 
   1083 //----------------------------------------------------------------------------------
   1084 // ActiveStateChanged
   1085 //----------------------------------------------------------------------------------
   1086 //
   1087 static void
   1088 ActiveStateChanged( HIWebView* view )
   1089 {
   1090 	if ( [view->fWebView respondsToSelector:@selector(setEnabled)] )
   1091 	{
   1092 		[(NSControl*)view->fWebView setEnabled: IsControlEnabled( view->fViewRef )];
   1093 		HIViewSetNeedsDisplay( view->fViewRef, true );
   1094 	}
   1095 }
   1096 
   1097 
   1098 //----------------------------------------------------------------------------------
   1099 // ProcessCommand
   1100 //----------------------------------------------------------------------------------
   1101 //
   1102 static OSStatus
   1103 ProcessCommand( HIWebView* inView, const HICommand* inCommand )
   1104 {
   1105 	OSStatus		result = eventNotHandledErr;
   1106 	NSResponder*	resp;
   1107 
   1108 	resp = [inView->fKitWindow firstResponder];
   1109 
   1110 	if ( [resp isKindOfClass:[NSView class]] )
   1111 	{
   1112 		NSView*	respView = (NSView*)resp;
   1113 
   1114 		if ( respView == inView->fWebView
   1115 			|| [respView isDescendantOf: inView->fWebView] )
   1116 		{
   1117 			switch ( inCommand->commandID )
   1118 			{
   1119 				case kHICommandCut:
   1120 				case kHICommandCopy:
   1121 				case kHICommandPaste:
   1122 				case kHICommandClear:
   1123 				case kHICommandSelectAll:
   1124 					{
   1125 						SEL selector = _NSSelectorForHICommand( inCommand );
   1126 						if ( [respView respondsToSelector:selector] )
   1127 						{
   1128 							[respView performSelector:selector withObject:nil];
   1129 							result = noErr;
   1130 						}
   1131 					}
   1132 					break;
   1133 			}
   1134 		}
   1135 	}
   1136 
   1137 	return result;
   1138 }
   1139 
   1140 //----------------------------------------------------------------------------------
   1141 // UpdateCommandStatus
   1142 //----------------------------------------------------------------------------------
   1143 //
   1144 static OSStatus
   1145 UpdateCommandStatus( HIWebView* inView, const HICommand* inCommand )
   1146 {
   1147 	OSStatus		result = eventNotHandledErr;
   1148 	MenuItemProxy* 	proxy = NULL;
   1149 	NSResponder*	resp;
   1150 
   1151 	resp = [inView->fKitWindow firstResponder];
   1152 
   1153 	if ( [resp isKindOfClass:[NSView class]] )
   1154 	{
   1155 		NSView*	respView = (NSView*)resp;
   1156 
   1157 		if ( respView == inView->fWebView
   1158 			|| [respView isDescendantOf: inView->fWebView] )
   1159 		{
   1160 			if ( inCommand->attributes & kHICommandFromMenu )
   1161 			{
   1162 				SEL selector = _NSSelectorForHICommand( inCommand );
   1163 
   1164 				if ( selector )
   1165 				{
   1166 					if ( [resp respondsToSelector: selector] )
   1167 					{
   1168 						proxy = [[MenuItemProxy alloc] initWithAction: selector];
   1169 
   1170                         // Can't use -performSelector:withObject: here because the method we're calling returns BOOL, while
   1171                         // -performSelector:withObject:'s return value is assumed to be an id.
   1172                         BOOL (*validationFunction)(id, SEL, id) = (BOOL (*)(id, SEL, id))objc_msgSend;
   1173                         if (validationFunction(resp, @selector(validateUserInterfaceItem:), proxy))
   1174 							EnableMenuItem( inCommand->menu.menuRef, inCommand->menu.menuItemIndex );
   1175 						else
   1176 							DisableMenuItem( inCommand->menu.menuRef, inCommand->menu.menuItemIndex );
   1177 
   1178 						result = noErr;
   1179 					}
   1180 				}
   1181 			}
   1182 		}
   1183 	}
   1184 
   1185 	if ( proxy )
   1186 		[proxy release];
   1187 
   1188 	return result;
   1189 }
   1190 
   1191 // Blatantly stolen from AppKit and cropped a bit
   1192 
   1193 //----------------------------------------------------------------------------------
   1194 // _NSSelectorForHICommand
   1195 //----------------------------------------------------------------------------------
   1196 //
   1197 static SEL
   1198 _NSSelectorForHICommand( const HICommand* inCommand )
   1199 {
   1200     switch ( inCommand->commandID )
   1201 	{
   1202         case kHICommandUndo: return @selector(undo:);
   1203         case kHICommandRedo: return @selector(redo:);
   1204         case kHICommandCut  : return @selector(cut:);
   1205         case kHICommandCopy : return @selector(copy:);
   1206         case kHICommandPaste: return @selector(paste:);
   1207         case kHICommandClear: return @selector(delete:);
   1208         case kHICommandSelectAll: return @selector(selectAll:);
   1209         default: return NULL;
   1210     }
   1211 
   1212     return NULL;
   1213 }
   1214 
   1215 
   1216 //-----------------------------------------------------------------------------------
   1217 //	HIWebViewEventHandler
   1218 //-----------------------------------------------------------------------------------
   1219 //	Our object's virtual event handler method. I'm not sure if we need this these days.
   1220 //	We used to do various things with it, but those days are long gone...
   1221 //
   1222 static OSStatus
   1223 HIWebViewEventHandler(
   1224 	EventHandlerCallRef	inCallRef,
   1225 	EventRef			inEvent,
   1226 	void *				inUserData )
   1227 {
   1228 	OSStatus			result = eventNotHandledErr;
   1229 	HIPoint				where;
   1230 	OSType				tag;
   1231 	void *				ptr;
   1232 	Size				size;
   1233 	UInt32				features;
   1234 	RgnHandle			region = NULL;
   1235 	ControlPartCode		part;
   1236 	HIWebView*			view = (HIWebView*)inUserData;
   1237 
   1238         // [NSApp setWindowsNeedUpdate:YES] must be called before events so that ActivateTSMDocument is called to set an active document.
   1239         // Without an active document, TSM will use a default document which uses a bottom-line input window which we don't want.
   1240         [NSApp setWindowsNeedUpdate:YES];
   1241 
   1242 	switch ( GetEventClass( inEvent ) )
   1243 	{
   1244 		case kEventClassHIObject:
   1245 			switch ( GetEventKind( inEvent ) )
   1246 			{
   1247 				case kEventHIObjectConstruct:
   1248 					{
   1249 						HIObjectRef		object;
   1250 
   1251 						result = GetEventParameter( inEvent, kEventParamHIObjectInstance,
   1252 								typeHIObjectRef, NULL, sizeof( HIObjectRef ), NULL, &object );
   1253 						require_noerr( result, MissingParameter );
   1254 
   1255 						// on entry for our construct event, we're passed the
   1256 						// creation proc we registered with for this class.
   1257 						// we use it now to create the instance, and then we
   1258 						// replace the instance parameter data with said instance
   1259 						// as type void.
   1260 
   1261 						view = HIWebViewConstructor( (HIViewRef)object );
   1262 
   1263 						if ( view )
   1264 						{
   1265 							SetEventParameter( inEvent, kEventParamHIObjectInstance,
   1266 									typeVoidPtr, sizeof( void * ), &view );
   1267 						}
   1268 					}
   1269 					break;
   1270 
   1271 				case kEventHIObjectDestruct:
   1272 					HIWebViewDestructor( view );
   1273 					// result is unimportant
   1274 					break;
   1275 			}
   1276 			break;
   1277 
   1278 		case kEventClassKeyboard:
   1279 			{
   1280 				NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
   1281 				[view->fKitWindow sendSuperEvent:kitEvent];
   1282 				[kitEvent release];
   1283 				result = noErr;
   1284 			}
   1285 			break;
   1286 
   1287 		case kEventClassMouse:
   1288 			switch ( GetEventKind( inEvent ) )
   1289 			{
   1290 				case kEventMouseUp:
   1291 					result = MouseUp( view, inEvent );
   1292 					break;
   1293 
   1294 				case kEventMouseWheelMoved:
   1295 					result = MouseWheelMoved( view, inEvent );
   1296 					break;
   1297 
   1298 				case kEventMouseMoved:
   1299 					result = MouseMoved( view, inEvent );
   1300 					break;
   1301 
   1302 				case kEventMouseDragged:
   1303 					result = MouseDragged( view, inEvent );
   1304 					break;
   1305 			}
   1306 			break;
   1307 
   1308 		case kEventClassCommand:
   1309 			{
   1310 				HICommand		command;
   1311 
   1312 				result = GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL,
   1313 								sizeof( HICommand ), NULL, &command );
   1314 				require_noerr( result, MissingParameter );
   1315 
   1316 				switch ( GetEventKind( inEvent ) )
   1317 				{
   1318 					case kEventCommandProcess:
   1319 						result = ProcessCommand( view, &command );
   1320 						break;
   1321 
   1322 					case kEventCommandUpdateStatus:
   1323 						result = UpdateCommandStatus( view, &command );
   1324 						break;
   1325 				}
   1326 			}
   1327 			break;
   1328 
   1329 		case kEventClassControl:
   1330 			switch ( GetEventKind( inEvent ) )
   1331 			{
   1332 				case kEventControlInitialize:
   1333 					features = GetBehaviors();
   1334 					SetEventParameter( inEvent, kEventParamControlFeatures, typeUInt32,
   1335 							sizeof( UInt32 ), &features );
   1336 					result = noErr;
   1337 					break;
   1338 
   1339 				case kEventControlDraw:
   1340 					{
   1341 						CGContextRef		context = NULL;
   1342 
   1343 						GetEventParameter( inEvent, kEventParamRgnHandle, typeQDRgnHandle, NULL,
   1344 								sizeof( RgnHandle ), NULL, &region );
   1345 						GetEventParameter( inEvent, kEventParamCGContextRef, typeCGContextRef, NULL,
   1346 								sizeof( CGContextRef ), NULL, &context );
   1347 
   1348 						Draw( view, region, context );
   1349 
   1350 						result = noErr;
   1351 					}
   1352 					break;
   1353 
   1354 				case kEventControlHitTest:
   1355 					GetEventParameter( inEvent, kEventParamMouseLocation, typeHIPoint, NULL,
   1356 							sizeof( HIPoint ), NULL, &where );
   1357 					part = HitTest( view, &where );
   1358 					SetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, sizeof( ControlPartCode ), &part );
   1359 					result = noErr;
   1360 					break;
   1361 
   1362 				case kEventControlGetPartRegion:
   1363 					GetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, NULL,
   1364 							sizeof( ControlPartCode ), NULL, &part );
   1365 					GetEventParameter( inEvent, kEventParamControlRegion, typeQDRgnHandle, NULL,
   1366 							sizeof( RgnHandle ), NULL, &region );
   1367 					result = GetRegion( view, part, region );
   1368 					break;
   1369 
   1370 				case kEventControlGetData:
   1371 					GetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, NULL, sizeof(ControlPartCode), NULL, &part);
   1372 					GetEventParameter(inEvent, kEventParamControlDataTag, typeEnumeration, NULL, sizeof(OSType), NULL, &tag);
   1373 					GetEventParameter(inEvent, kEventParamControlDataBuffer, typePtr, NULL, sizeof(Ptr), NULL, &ptr);
   1374 					GetEventParameter(inEvent, kEventParamControlDataBufferSize, typeByteCount, NULL, sizeof(Size), NULL, &size);
   1375 
   1376 					if (tag == kControlKindTag) {
   1377 						Size outSize;
   1378 						result = noErr;
   1379 
   1380 						if (ptr) {
   1381 							if (size != sizeof(ControlKind))
   1382 								result = errDataSizeMismatch;
   1383 							else
   1384 								(*(ControlKind *)ptr) = GetKind();
   1385 						}
   1386 
   1387 						outSize = sizeof(ControlKind);
   1388 						SetEventParameter(inEvent, kEventParamControlDataBufferSize, typeByteCount, sizeof(Size), &outSize);
   1389 					}
   1390 
   1391 					break;
   1392 
   1393 				case kEventControlBoundsChanged:
   1394 					{
   1395 						HIRect		prevRect, currRect;
   1396 						UInt32		attrs;
   1397 
   1398 						GetEventParameter( inEvent, kEventParamAttributes, typeUInt32, NULL,
   1399 								sizeof( UInt32 ), NULL, &attrs );
   1400 						GetEventParameter( inEvent, kEventParamOriginalBounds, typeHIRect, NULL,
   1401 								sizeof( HIRect ), NULL, &prevRect );
   1402 						GetEventParameter( inEvent, kEventParamCurrentBounds, typeHIRect, NULL,
   1403 								sizeof( HIRect ), NULL, &currRect );
   1404 
   1405 						BoundsChanged( view, attrs, &prevRect, &currRect );
   1406 						result = noErr;
   1407 					}
   1408 					break;
   1409 
   1410 				case kEventControlActivate:
   1411 					ActiveStateChanged( view );
   1412 					result = noErr;
   1413 					break;
   1414 
   1415 				case kEventControlDeactivate:
   1416 					ActiveStateChanged( view );
   1417 					result = noErr;
   1418 					break;
   1419 
   1420 				case kEventControlOwningWindowChanged:
   1421 					{
   1422 						WindowRef		fromWindow, toWindow;
   1423 
   1424 						result = GetEventParameter( inEvent, kEventParamControlOriginalOwningWindow, typeWindowRef, NULL,
   1425 										sizeof( WindowRef ), NULL, &fromWindow );
   1426 						require_noerr( result, MissingParameter );
   1427 
   1428 						result = GetEventParameter( inEvent, kEventParamControlCurrentOwningWindow, typeWindowRef, NULL,
   1429 										sizeof( WindowRef ), NULL, &toWindow );
   1430 						require_noerr( result, MissingParameter );
   1431 
   1432 						OwningWindowChanged( view, fromWindow, toWindow );
   1433 
   1434 						result = noErr;
   1435 					}
   1436 					break;
   1437 
   1438 				case kEventControlClick:
   1439 					result = Click( view, inEvent );
   1440 					break;
   1441 
   1442 				case kEventControlContextualMenuClick:
   1443 					result = ContextMenuClick( view, inEvent );
   1444 					break;
   1445 
   1446 				case kEventControlSetFocusPart:
   1447 					{
   1448 						ControlPartCode		desiredFocus;
   1449 						RgnHandle			invalidRgn;
   1450 						Boolean				focusEverything;
   1451 						ControlPartCode		actualFocus;
   1452 
   1453 						result = GetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, NULL,
   1454 										sizeof( ControlPartCode ), NULL, &desiredFocus );
   1455 						require_noerr( result, MissingParameter );
   1456 
   1457 						GetEventParameter( inEvent, kEventParamControlInvalRgn, typeQDRgnHandle, NULL,
   1458 								sizeof( RgnHandle ), NULL, &invalidRgn );
   1459 
   1460 						focusEverything = false; // a good default in case the parameter doesn't exist
   1461 
   1462 						GetEventParameter( inEvent, kEventParamControlFocusEverything, typeBoolean, NULL,
   1463 								sizeof( Boolean ), NULL, &focusEverything );
   1464 
   1465 						result = SetFocusPart( view, desiredFocus, invalidRgn, focusEverything, &actualFocus );
   1466 
   1467 						if ( result == noErr )
   1468 							verify_noerr( SetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode,
   1469 									sizeof( ControlPartCode ), &actualFocus ) );
   1470 					}
   1471 					break;
   1472 
   1473 				// some other kind of Control event
   1474 				default:
   1475 					break;
   1476 			}
   1477 			break;
   1478 
   1479 		// some other event class
   1480 		default:
   1481 			break;
   1482 	}
   1483 
   1484 MissingParameter:
   1485 	return result;
   1486 }
   1487 
   1488 
   1489 static void UpdateObserver(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info);
   1490 
   1491 static void
   1492 StartUpdateObserver( HIWebView* view )
   1493 {
   1494 	CFRunLoopObserverContext	context;
   1495 	CFRunLoopObserverRef		observer;
   1496     CFRunLoopRef				mainRunLoop;
   1497 
   1498     check( view->fIsComposited == false );
   1499     check( view->fUpdateObserver == NULL );
   1500 
   1501 	context.version = 0;
   1502 	context.info = view;
   1503 	context.retain = NULL;
   1504 	context.release = NULL;
   1505 	context.copyDescription = NULL;
   1506 
   1507     mainRunLoop = (CFRunLoopRef)GetCFRunLoopFromEventLoop( GetMainEventLoop() );
   1508 	observer = CFRunLoopObserverCreate( NULL, kCFRunLoopEntry | kCFRunLoopBeforeWaiting, true, 0, UpdateObserver, &context );
   1509 	CFRunLoopAddObserver( mainRunLoop, observer, kCFRunLoopCommonModes );
   1510 
   1511     view->fUpdateObserver = observer;
   1512 
   1513 //    printf( "Update observer started\n" );
   1514 }
   1515 
   1516 static void
   1517 StopUpdateObserver( HIWebView* view )
   1518 {
   1519     check( view->fIsComposited == false );
   1520     check( view->fUpdateObserver != NULL );
   1521 
   1522     CFRunLoopObserverInvalidate( view->fUpdateObserver );
   1523     CFRelease( view->fUpdateObserver );
   1524     view->fUpdateObserver = NULL;
   1525 
   1526 //    printf( "Update observer removed\n" );
   1527 }
   1528 
   1529 static void
   1530 UpdateObserver( CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info )
   1531 {
   1532 	HIWebView*			view = (HIWebView*)info;
   1533     RgnHandle			region = NewRgn();
   1534 
   1535 //    printf( "Update observer called\n" );
   1536 
   1537     if ( region )
   1538     {
   1539         GetWindowRegion( GetControlOwner( view->fViewRef ), kWindowUpdateRgn, region );
   1540 
   1541         if ( !EmptyRgn( region ) )
   1542         {
   1543             RgnHandle		ourRgn = NewRgn();
   1544             Rect			rect;
   1545 
   1546             GetWindowBounds( GetControlOwner( view->fViewRef ), kWindowStructureRgn, &rect );
   1547 
   1548 //            printf( "Update region is non-empty\n" );
   1549 
   1550             if ( ourRgn )
   1551             {
   1552                 Rect		rect;
   1553                 GrafPtr		savePort, port;
   1554                 Point		offset = { 0, 0 };
   1555 
   1556                 port = GetWindowPort( GetControlOwner( view->fViewRef ) );
   1557 
   1558                 GetPort( &savePort );
   1559                 SetPort( port );
   1560 
   1561                 GlobalToLocal( &offset );
   1562                 OffsetRgn( region, offset.h, offset.v );
   1563 
   1564                 GetControlBounds( view->fViewRef, &rect );
   1565                 RectRgn( ourRgn, &rect );
   1566 
   1567 //                printf( "our control is at %d %d %d %d\n",
   1568 //                        rect.top, rect.left, rect.bottom, rect.right );
   1569 
   1570                 GetRegionBounds( region, &rect );
   1571 //                printf( "region is at %d %d %d %d\n",
   1572 //                        rect.top, rect.left, rect.bottom, rect.right );
   1573 
   1574                 SectRgn( ourRgn, region, ourRgn );
   1575 
   1576                 GetRegionBounds( ourRgn, &rect );
   1577 //                printf( "intersection is  %d %d %d %d\n",
   1578 //                       rect.top, rect.left, rect.bottom, rect.right );
   1579                 if ( !EmptyRgn( ourRgn ) )
   1580                 {
   1581                     RgnHandle	saveVis = NewRgn();
   1582 
   1583 //                    printf( "looks like we should draw\n" );
   1584 
   1585                     if ( saveVis )
   1586                     {
   1587 //                        RGBColor	kRedColor = { 0xffff, 0, 0 };
   1588 
   1589                         GetPortVisibleRegion( GetWindowPort( GetControlOwner( view->fViewRef ) ), saveVis );
   1590                         SetPortVisibleRegion( GetWindowPort( GetControlOwner( view->fViewRef ) ), ourRgn );
   1591 
   1592 //                        RGBForeColor( &kRedColor );
   1593 //                        PaintRgn( ourRgn );
   1594 //                        QDFlushPortBuffer( port, NULL );
   1595 //                        Delay( 15, NULL );
   1596 
   1597                         Draw1Control( view->fViewRef );
   1598                         ValidWindowRgn( GetControlOwner( view->fViewRef ), ourRgn );
   1599 
   1600                         SetPortVisibleRegion( GetWindowPort( GetControlOwner( view->fViewRef ) ), saveVis );
   1601                         DisposeRgn( saveVis );
   1602                     }
   1603                 }
   1604 
   1605                 SetPort( savePort );
   1606 
   1607                 DisposeRgn( ourRgn );
   1608             }
   1609         }
   1610 
   1611         DisposeRgn( region );
   1612     }
   1613 }
   1614 
   1615 #endif
   1616