webengine/osswebengine/WebKit/Carbon/HIWebView.m
changeset 0 dd21522fd290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/WebKit/Carbon/HIWebView.m	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,1639 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __LP64__
+
+#import "HIWebView.h"
+
+#import "CarbonWindowAdapter.h"
+#import "HIViewAdapter.h"
+#import "WebHTMLViewInternal.h"
+#import "WebKit.h"
+
+#import <objc/objc-runtime.h>
+#import <WebKitSystemInterface.h>
+
+@interface NSWindow (AppKitSecretsHIWebViewKnows)
+- (void)_removeWindowRef;
+@end
+
+@interface NSView (AppKitSecretsHIWebViewKnows)
+- (void)_clearDirtyRectsForTree;
+@end
+
+extern "C" void HIWebViewRegisterClass();
+
+@interface MenuItemProxy : NSObject <NSValidatedUserInterfaceItem>
+{
+    int     _tag;
+    SEL _action;
+}
+
+- (id)initWithAction:(SEL)action;
+- (SEL)action;
+- (int)tag;
+
+@end
+
+@implementation MenuItemProxy
+
+- (id)initWithAction:(SEL)action
+{
+    [super init];
+    if (self == nil) return nil;
+
+    _action = action;
+
+    return self;
+}
+
+- (SEL)action
+{
+       return _action;
+}
+
+- (int)tag 
+{
+    return 0;
+}
+
+@end
+
+struct HIWebView
+{
+    HIViewRef							fViewRef;
+
+    WebView*							fWebView;
+    NSView*								fFirstResponder;
+    CarbonWindowAdapter	*				fKitWindow;
+    bool								fIsComposited;
+    CFRunLoopObserverRef				fUpdateObserver;
+};
+typedef struct HIWebView HIWebView;
+
+static const OSType NSAppKitPropertyCreator = 'akit';
+/*
+These constants are not used. Commented out to make the compiler happy.
+static const OSType NSViewCarbonControlViewPropertyTag = 'view';
+static const OSType NSViewCarbonControlAutodisplayPropertyTag = 'autd';
+static const OSType NSViewCarbonControlFirstResponderViewPropertyTag = 'frvw';
+*/
+static const OSType NSCarbonWindowPropertyTag = 'win ';
+
+#ifdef BUILDING_ON_TIGER
+const int typeByteCount = typeSInt32;
+#endif
+
+static SEL _NSSelectorForHICommand( const HICommand* hiCommand );
+
+static const EventTypeSpec kEvents[] = { 
+	{ kEventClassHIObject, kEventHIObjectConstruct },
+	{ kEventClassHIObject, kEventHIObjectDestruct },
+	
+	{ kEventClassMouse, kEventMouseUp },
+	{ kEventClassMouse, kEventMouseMoved },
+	{ kEventClassMouse, kEventMouseDragged },
+	{ kEventClassMouse, kEventMouseWheelMoved },
+
+	{ kEventClassKeyboard, kEventRawKeyDown },
+	{ kEventClassKeyboard, kEventRawKeyRepeat },
+
+	{ kEventClassCommand, kEventCommandProcess },
+	{ kEventClassCommand, kEventCommandUpdateStatus },
+
+	{ kEventClassControl, kEventControlInitialize },
+	{ kEventClassControl, kEventControlDraw },
+	{ kEventClassControl, kEventControlHitTest },
+	{ kEventClassControl, kEventControlGetPartRegion },
+	{ kEventClassControl, kEventControlGetData },
+	{ kEventClassControl, kEventControlBoundsChanged },
+	{ kEventClassControl, kEventControlActivate },
+	{ kEventClassControl, kEventControlDeactivate },
+	{ kEventClassControl, kEventControlOwningWindowChanged },
+	{ kEventClassControl, kEventControlClick },
+	{ kEventClassControl, kEventControlContextualMenuClick },
+	{ kEventClassControl, kEventControlSetFocusPart }
+};
+
+#define kHIViewBaseClassID		CFSTR( "com.apple.hiview" )
+#define kHIWebViewClassID		CFSTR( "com.apple.HIWebView" )
+
+static HIWebView*		HIWebViewConstructor( HIViewRef inView );
+static void				HIWebViewDestructor( HIWebView* view );
+
+static OSStatus			HIWebViewEventHandler(
+								EventHandlerCallRef	inCallRef,
+								EventRef			inEvent,
+								void *				inUserData );
+
+static UInt32			GetBehaviors();
+static ControlKind		GetKind();
+static void				Draw( HIWebView* inView, RgnHandle limitRgn, CGContextRef inContext );
+static ControlPartCode	HitTest( HIWebView* view, const HIPoint* where );
+static OSStatus			GetRegion( HIWebView* view, ControlPartCode inPart, RgnHandle outRgn );
+static void				BoundsChanged(
+								HIWebView*			inView,
+								UInt32				inOptions,
+								const HIRect*		inOriginalBounds,
+								const HIRect*		inCurrentBounds );
+static void				OwningWindowChanged(
+								HIWebView*			view,
+								WindowRef			oldWindow,
+								WindowRef			newWindow );
+static void				ActiveStateChanged( HIWebView* view );
+
+static OSStatus			Click( HIWebView* inView, EventRef inEvent );
+static OSStatus			ContextMenuClick( HIWebView* inView, EventRef inEvent );
+static OSStatus			MouseUp( HIWebView* inView, EventRef inEvent );
+static OSStatus			MouseMoved( HIWebView* inView, EventRef inEvent );
+static OSStatus			MouseDragged( HIWebView* inView, EventRef inEvent );
+static OSStatus			MouseWheelMoved( HIWebView* inView, EventRef inEvent );
+
+static OSStatus			ProcessCommand( HIWebView* inView, const HICommand* inCommand );
+static OSStatus			UpdateCommandStatus( HIWebView* inView, const HICommand* inCommand );
+
+static OSStatus			SetFocusPart(
+								HIWebView*				view,
+								ControlPartCode 		desiredFocus,
+								RgnHandle 				invalidRgn,
+								Boolean 				focusEverything,
+								ControlPartCode* 		actualFocus );
+static NSView*			AdvanceFocus( HIWebView* view, bool forward );
+static void				RelinquishFocus( HIWebView* view, bool inAutodisplay );
+
+static WindowRef		GetWindowRef( HIWebView* inView );
+static void				SyncFrame( HIWebView* inView );
+
+static OSStatus			WindowHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData );
+
+static void				StartUpdateObserver( HIWebView* view );
+static void				StopUpdateObserver( HIWebView* view );
+
+static inline void HIRectToQDRect( const HIRect* inRect, Rect* outRect )
+{
+    outRect->top = (SInt16)CGRectGetMinY( *inRect );
+    outRect->left = (SInt16)CGRectGetMinX( *inRect );
+    outRect->bottom = (SInt16)CGRectGetMaxY( *inRect );
+    outRect->right = (SInt16)CGRectGetMaxX( *inRect );
+}
+
+static Class webViewClass;
+
+//----------------------------------------------------------------------------------
+// HIWebViewCreate
+//----------------------------------------------------------------------------------
+//
+OSStatus
+HIWebViewCreate( HIViewRef* outControl )
+{
+	OSStatus			err;
+    
+	HIWebViewRegisterClass();
+
+    webViewClass = [WebView class];
+	err = HIObjectCreate( kHIWebViewClassID, NULL, (HIObjectRef*)outControl );
+
+	return err;
+}
+
+//----------------------------------------------------------------------------------
+// HIWebViewCreateWithClass
+//----------------------------------------------------------------------------------
+//
+OSStatus HIWebViewCreateWithClass(Class aClass, HIViewRef * outControl)
+{
+	OSStatus			err;
+    
+	HIWebViewRegisterClass();
+
+    webViewClass = aClass;
+	err = HIObjectCreate( kHIWebViewClassID, NULL, (HIObjectRef*)outControl );
+
+	return err;
+}
+
+//----------------------------------------------------------------------------------
+// HIWebViewGetWebView
+//----------------------------------------------------------------------------------
+//
+WebView*
+HIWebViewGetWebView( HIViewRef inView )
+{
+	HIWebView* 	view = (HIWebView*)HIObjectDynamicCast( (HIObjectRef)inView, kHIWebViewClassID );
+	WebView*			result = NULL;
+	
+	if ( view )
+		result = view->fWebView;
+	
+	return result;
+}
+
+//----------------------------------------------------------------------------------
+// HIWebViewConstructor
+//----------------------------------------------------------------------------------
+//
+
+static HIWebView*
+HIWebViewConstructor( HIViewRef inView )
+{
+	HIWebView*		view = (HIWebView*)malloc( sizeof( HIWebView ) );
+	
+	if ( view )
+	{
+		NSRect		frame = { { 0, 0 }, { 400, 400  } };
+	
+		view->fViewRef = inView;
+
+                WebView *webView = [[webViewClass alloc] initWithFrame: frame];
+                CFRetain(webView);
+                [webView release];
+		view->fWebView = webView;
+		[HIViewAdapter bindHIViewToNSView:inView nsView:view->fWebView];
+		
+		view->fFirstResponder = NULL;
+		view->fKitWindow = NULL;
+        view->fIsComposited = false;
+        view->fUpdateObserver = NULL;
+	}
+	
+	return view;
+}
+
+//----------------------------------------------------------------------------------
+// HIWebViewDestructor
+//----------------------------------------------------------------------------------
+//
+static void
+HIWebViewDestructor( HIWebView* inView )
+{
+    [HIViewAdapter unbindNSView:inView->fWebView];
+    CFRelease(inView->fWebView);
+
+    free(inView);
+}
+
+//----------------------------------------------------------------------------------
+// HIWebViewRegisterClass
+//----------------------------------------------------------------------------------
+//
+void
+HIWebViewRegisterClass()
+{
+	static bool sRegistered;
+	
+	if ( !sRegistered )
+	{
+		HIObjectRegisterSubclass( kHIWebViewClassID, kHIViewBaseClassID, 0, HIWebViewEventHandler,
+			GetEventTypeCount( kEvents ), kEvents, 0, NULL );
+		sRegistered = true;
+	}
+}
+
+//----------------------------------------------------------------------------------
+// GetBehaviors
+//----------------------------------------------------------------------------------
+//
+static UInt32
+GetBehaviors()
+{
+	return kControlSupportsDataAccess | kControlSupportsGetRegion | kControlGetsFocusOnClick;
+}
+
+//----------------------------------------------------------------------------------
+// Draw
+//----------------------------------------------------------------------------------
+//
+static void
+Draw( HIWebView* inView, RgnHandle limitRgn, CGContextRef inContext )
+{
+	HIRect				bounds;
+	Rect				drawRect;
+	HIRect				hiRect;
+	bool				createdContext = false;
+
+    if (!inView->fIsComposited)
+    {
+        GrafPtr port;
+        Rect portRect;
+
+        GetPort( &port );
+        GetPortBounds( port, &portRect );
+        CreateCGContextForPort( port, &inContext );
+        SyncCGContextOriginWithPort( inContext, port );
+        CGContextTranslateCTM( inContext, 0, (portRect.bottom - portRect.top) );
+        CGContextScaleCTM( inContext, 1, -1 );
+        createdContext = true;
+    }
+
+	HIViewGetBounds( inView->fViewRef, &bounds );
+
+    CGContextRef savedContext = WKNSWindowOverrideCGContext(inView->fKitWindow, inContext);
+    [NSGraphicsContext setCurrentContext:[inView->fKitWindow graphicsContext]];
+
+	GetRegionBounds( limitRgn, &drawRect );
+
+    if ( !inView->fIsComposited )
+        OffsetRect( &drawRect, (SInt16)-bounds.origin.x, (SInt16)-bounds.origin.y );
+    
+	hiRect.origin.x = drawRect.left;
+	hiRect.origin.y = bounds.size.height - drawRect.bottom; // flip y
+	hiRect.size.width = drawRect.right - drawRect.left;
+	hiRect.size.height = drawRect.bottom - drawRect.top;
+
+//    printf( "Drawing: drawRect is (%g %g) (%g %g)\n", hiRect.origin.x, hiRect.origin.y,
+//            hiRect.size.width, hiRect.size.height );
+
+    // FIXME: We need to do layout before Carbon has decided what region needs drawn.
+    // In Cocoa we make sure to do layout and invalidate any new regions before draw, so everything
+    // can be drawn in one pass. Doing a layout here will cause new regions to be invalidated, but they
+    // will not all be drawn in this pass since we already have a fixed rect we are going to display.
+
+    NSView <WebDocumentView> *documentView = [[[inView->fWebView mainFrame] frameView] documentView];
+    if ([documentView isKindOfClass:[WebHTMLView class]])
+        [(WebHTMLView *)documentView _web_layoutIfNeededRecursive];
+
+    if ( inView->fIsComposited )
+        [inView->fWebView displayIfNeededInRect: *(NSRect*)&hiRect];
+    else
+        [inView->fWebView displayRect:*(NSRect*)&hiRect];
+
+    WKNSWindowRestoreCGContext(inView->fKitWindow, savedContext);
+
+    if ( !inView->fIsComposited )
+    {
+        HIViewRef      view;
+        HIViewFindByID( HIViewGetRoot( GetControlOwner( inView->fViewRef ) ), kHIViewWindowGrowBoxID, &view );
+        if ( view )
+        {
+            HIRect     frame;
+
+            HIViewGetBounds( view, &frame );
+            HIViewConvertRect( &frame, view, NULL );
+
+            hiRect.origin.x = drawRect.left;
+            hiRect.origin.y = drawRect.top;
+            hiRect.size.width = drawRect.right - drawRect.left;
+            hiRect.size.height = drawRect.bottom - drawRect.top;
+
+            HIViewConvertRect( &hiRect, inView->fViewRef, NULL );
+
+            if ( CGRectIntersectsRect( frame, hiRect ) )
+                HIViewSetNeedsDisplay( view, true );
+        }
+     }
+
+    if ( createdContext )
+    {
+        CGContextSynchronize( inContext );
+        CGContextRelease( inContext );
+    }
+}
+
+//----------------------------------------------------------------------------------
+// HitTest
+//----------------------------------------------------------------------------------
+//
+static ControlPartCode
+HitTest( HIWebView* view, const HIPoint* where )
+{
+	HIRect		bounds;
+	
+	HIViewGetBounds( view->fViewRef, &bounds );
+
+	if ( CGRectContainsPoint( bounds, *where ) )
+		return 1;
+	else
+		return kControlNoPart;
+}
+
+//----------------------------------------------------------------------------------
+// GetRegion
+//----------------------------------------------------------------------------------
+//
+static OSStatus
+GetRegion(
+	HIWebView*			inView,
+	ControlPartCode		inPart,
+	RgnHandle			outRgn )
+{
+	OSStatus	 err = eventNotHandledErr;
+	
+	if ( inPart == -3 ) // kControlOpaqueMetaPart:
+	{
+		if ( [inView->fWebView isOpaque] )
+		{
+			HIRect	bounds;
+			Rect	temp;
+			
+			HIViewGetBounds( inView->fViewRef, &bounds );
+
+			temp.top = (SInt16)bounds.origin.y;
+			temp.left = (SInt16)bounds.origin.x;
+			temp.bottom = (SInt16)CGRectGetMaxY( bounds );
+			temp.right = (SInt16)CGRectGetMaxX( bounds );
+
+			RectRgn( outRgn, &temp );
+			err = noErr;
+		}
+	}
+	
+	return err;
+}
+
+static WindowRef
+GetWindowRef( HIWebView* inView )
+{
+       return GetControlOwner( inView->fViewRef );
+}
+
+//----------------------------------------------------------------------------------
+// Click
+//----------------------------------------------------------------------------------
+//
+static OSStatus
+Click(HIWebView* inView, EventRef inEvent)
+{
+    NSEvent *kitEvent = WKCreateNSEventWithCarbonClickEvent(inEvent, GetWindowRef(inView));
+
+    if (!inView->fIsComposited)
+        StartUpdateObserver(inView);
+
+    [inView->fKitWindow sendEvent:kitEvent];
+
+    if (!inView->fIsComposited)
+        StopUpdateObserver(inView);
+
+    [kitEvent release];
+
+    return noErr;
+}
+
+//----------------------------------------------------------------------------------
+// MouseUp
+//----------------------------------------------------------------------------------
+//
+static OSStatus
+MouseUp( HIWebView* inView, EventRef inEvent )
+{
+	NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
+
+    [inView->fKitWindow sendEvent:kitEvent];
+	
+    [kitEvent release];
+    
+	return noErr;
+}
+
+//----------------------------------------------------------------------------------
+// MouseMoved
+//----------------------------------------------------------------------------------
+//
+static OSStatus
+MouseMoved( HIWebView* inView, EventRef inEvent )
+{
+    NSEvent *kitEvent = WKCreateNSEventWithCarbonMouseMoveEvent(inEvent, inView->fKitWindow);
+    [inView->fKitWindow sendEvent:kitEvent];
+	[kitEvent release];
+
+	return noErr;
+}
+
+//----------------------------------------------------------------------------------
+// MouseDragged
+//----------------------------------------------------------------------------------
+//
+static OSStatus
+MouseDragged( HIWebView* inView, EventRef inEvent )
+{
+	NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
+
+    [inView->fKitWindow sendEvent:kitEvent];
+
+	[kitEvent release];
+	
+	return noErr;
+}
+
+//----------------------------------------------------------------------------------
+// MouseDragged
+//----------------------------------------------------------------------------------
+//
+static OSStatus
+MouseWheelMoved( HIWebView* inView, EventRef inEvent )
+{
+	NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
+
+    [inView->fKitWindow sendEvent:kitEvent];
+
+	[kitEvent release];
+	
+	return noErr;
+}
+
+//----------------------------------------------------------------------------------
+// ContextMenuClick
+//----------------------------------------------------------------------------------
+//
+static OSStatus
+ContextMenuClick( HIWebView* inView, EventRef inEvent )
+{
+    NSView *webView = inView->fWebView;
+    NSWindow *window = [webView window];
+
+    // Get the point out of the event.
+    HIPoint point;
+    GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(point), NULL, &point);
+    HIViewConvertPoint(&point, inView->fViewRef, NULL);
+    
+    // Flip the Y coordinate, since Carbon is flipped relative to the AppKit.
+    NSPoint location = NSMakePoint(point.x, [window frame].size.height - point.y);
+    
+    // Make up an event with the point and send it to the window.
+    NSEvent *kitEvent = [NSEvent mouseEventWithType:NSRightMouseDown
+                                           location:location
+                                      modifierFlags:0
+                                          timestamp:GetEventTime(inEvent)
+                                       windowNumber:[window windowNumber]
+                                            context:0
+                                        eventNumber:0
+                                         clickCount:1
+                                           pressure:0];
+    [inView->fKitWindow sendEvent:kitEvent];
+    return noErr;
+}
+
+//----------------------------------------------------------------------------------
+// GetKind
+//----------------------------------------------------------------------------------
+//
+static ControlKind
+GetKind()
+{
+	const ControlKind kMyKind = { 'appl', 'wbvw' };
+	
+	return kMyKind;
+}
+
+//----------------------------------------------------------------------------------
+// BoundsChanged
+//----------------------------------------------------------------------------------
+//
+static void
+BoundsChanged(
+	HIWebView*			inView,
+	UInt32				inOptions,
+	const HIRect*		inOriginalBounds,
+	const HIRect*		inCurrentBounds )
+{
+	if ( inView->fWebView )
+	{
+		SyncFrame( inView );
+	}
+}
+
+//----------------------------------------------------------------------------------
+// OwningWindowChanged
+//----------------------------------------------------------------------------------
+//
+static void
+OwningWindowChanged(
+	HIWebView*			view,
+	WindowRef			oldWindow,
+	WindowRef			newWindow )
+{
+    if ( newWindow ){
+        WindowAttributes	attrs;
+        
+        OSStatus err = GetWindowProperty(newWindow, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &view->fKitWindow);
+        if ( err != noErr )
+        {
+            const EventTypeSpec kWindowEvents[] = {
+            { kEventClassWindow, kEventWindowClosed },
+            { kEventClassMouse, kEventMouseMoved },
+            { kEventClassMouse, kEventMouseUp },
+            { kEventClassMouse, kEventMouseDragged },
+            { kEventClassMouse, kEventMouseWheelMoved },
+            { kEventClassKeyboard, kEventRawKeyDown },
+            { kEventClassKeyboard, kEventRawKeyRepeat },
+            { kEventClassKeyboard, kEventRawKeyUp },
+            { kEventClassControl, kEventControlClick },
+            };
+            
+            view->fKitWindow = [[CarbonWindowAdapter alloc] initWithCarbonWindowRef: newWindow takingOwnership: NO disableOrdering:NO carbon:YES];
+            SetWindowProperty(newWindow, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), &view->fKitWindow);
+            
+            InstallWindowEventHandler( newWindow, WindowHandler, GetEventTypeCount( kWindowEvents ), kWindowEvents, newWindow, NULL );
+        }
+        
+        [[view->fKitWindow contentView] addSubview:view->fWebView];
+        
+        GetWindowAttributes( newWindow, &attrs );
+        view->fIsComposited = ( ( attrs & kWindowCompositingAttribute ) != 0 );
+        
+        SyncFrame( view );        
+    }
+    else
+    {
+        // Be sure to detach the cocoa view, too.
+        if ( view->fWebView )
+            [view->fWebView removeFromSuperview];
+        
+        view->fKitWindow = NULL; // break the ties that bind
+    }
+}
+
+//-------------------------------------------------------------------------------------
+//	WindowHandler
+//-------------------------------------------------------------------------------------
+//	Redirect mouse events to the views beneath them. This is required for WebKit to work
+// 	properly. We install it once per window. We also tap into window close to release
+//	the NSWindow that shadows our Carbon window.
+//
+static OSStatus
+WindowHandler( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData )
+{
+	WindowRef	window = (WindowRef)inUserData;
+	OSStatus	result = eventNotHandledErr;
+
+    switch( GetEventClass( inEvent ) )
+    {
+    	case kEventClassControl:
+            {
+            switch( GetEventKind( inEvent ) )
+            {
+                case kEventControlClick:
+                    {
+                        CarbonWindowAdapter *kitWindow;
+                        OSStatus err;
+                        
+                        err = GetWindowProperty( window, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &kitWindow);
+                        
+                        // We must be outside the HIWebView, relinquish focus.
+                        [kitWindow relinquishFocus];
+                    }
+                    break;
+                }
+            }
+            break;
+            
+    	case kEventClassKeyboard:
+    		{
+                NSWindow*		kitWindow;
+                OSStatus		err;
+   				NSEvent*		kitEvent;
+   				
+   				// if the first responder in the kit window is something other than the
+   				// window, we assume a subview of the webview is focused. we must send
+   				// the event to the window so that it goes through the kit's normal TSM
+   				// logic, and -- more importantly -- allows any delegates associated
+   				// with the first responder to have a chance at the event.
+   				
+				err = GetWindowProperty( window, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &kitWindow);
+				if ( err == noErr )
+				{
+					NSResponder* responder = [kitWindow firstResponder];
+					if ( responder != kitWindow )
+					{
+                        kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
+						
+						[kitWindow sendEvent:kitEvent];
+						[kitEvent release];
+						
+						result = noErr;
+					}
+				}
+    		}
+    		break;
+
+        case kEventClassWindow:
+            {
+                NSWindow*	kitWindow;
+                OSStatus	err;
+                
+                err = GetWindowProperty( window, NSAppKitPropertyCreator, NSCarbonWindowPropertyTag, sizeof(NSWindow *), NULL, &kitWindow);
+                if ( err == noErr )
+                {
+                    [kitWindow _removeWindowRef];
+                    [kitWindow close];
+                }
+	
+                result = noErr;
+            }
+            break;
+        
+        case kEventClassMouse:
+            switch (GetEventKind(inEvent))
+            {
+                case kEventMouseMoved:
+                    {
+                        Point where;
+                        GetEventParameter(inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &where);
+
+                        WindowRef temp;
+                        FindWindow(where, &temp);
+                        if (temp == window)
+                        {
+                            Rect bounds;
+                            GetWindowBounds(window, kWindowStructureRgn, &bounds);
+                            where.h -= bounds.left;
+                            where.v -= bounds.top;
+                            SetEventParameter(inEvent, kEventParamWindowRef, typeWindowRef, sizeof(WindowRef), &window);
+                            SetEventParameter(inEvent, kEventParamWindowMouseLocation, typeQDPoint, sizeof(Point), &where);
+
+                            OSStatus err = noErr;
+                            HIViewRef view = NULL;
+
+                            err = HIViewGetViewForMouseEvent(HIViewGetRoot(window), inEvent, &view);
+                            if (err == noErr && view && HIObjectIsOfClass((HIObjectRef)view, kHIWebViewClassID))
+                                result = SendEventToEventTargetWithOptions(inEvent, HIObjectGetEventTarget((HIObjectRef)view), kEventTargetDontPropagate);
+                        }
+                    }
+                    break;
+                
+                case kEventMouseUp:
+                case kEventMouseDragged:
+                case kEventMouseWheelMoved:
+                    {
+                        OSStatus err = noErr;
+                        HIViewRef view = NULL;
+
+                        err = HIViewGetViewForMouseEvent(HIViewGetRoot(window), inEvent, &view);
+                        if (err == noErr && view && HIObjectIsOfClass((HIObjectRef)view, kHIWebViewClassID))
+                            result = SendEventToEventTargetWithOptions(inEvent, HIObjectGetEventTarget((HIObjectRef)view), kEventTargetDontPropagate);
+                    }
+                    break;
+            }
+            break;
+    }
+
+	return result;
+}
+
+
+//----------------------------------------------------------------------------------
+// SyncFrame
+//----------------------------------------------------------------------------------
+//
+static void
+SyncFrame( HIWebView* inView )
+{
+	HIViewRef	parent = HIViewGetSuperview( inView->fViewRef );
+	
+	if ( parent )
+	{
+        if ( inView->fIsComposited )
+        {
+            HIRect		frame;
+            HIRect		parentBounds;
+            NSPoint		origin;
+
+            HIViewGetFrame( inView->fViewRef, &frame );
+            HIViewGetBounds( parent, &parentBounds );
+            
+            origin.x = frame.origin.x;
+            origin.y = parentBounds.size.height - CGRectGetMaxY( frame );
+//    printf( "syncing to (%g %g) (%g %g)\n", origin.x, origin.y,
+//            frame.size.width, frame.size.height );
+            [inView->fWebView setFrameOrigin: origin];
+            [inView->fWebView setFrameSize: *(NSSize*)&frame.size];
+        }
+        else
+        {
+            GrafPtr			port = GetWindowPort( GetControlOwner( inView->fViewRef ) );
+            PixMapHandle	portPix = GetPortPixMap( port );
+            Rect			bounds;
+            HIRect			rootFrame;
+            HIRect			frame;
+
+            GetControlBounds( inView->fViewRef, &bounds );
+            OffsetRect( &bounds, -(**portPix).bounds.left, -(**portPix).bounds.top );
+
+//            printf( "control lives at %d %d %d %d in window-coords\n", bounds.top, bounds.left,
+//                bounds.bottom, bounds.right );
+  
+            HIViewGetFrame( HIViewGetRoot( GetControlOwner( inView->fViewRef ) ), &rootFrame );
+
+            frame.origin.x = bounds.left;
+            frame.origin.y = rootFrame.size.height - bounds.bottom;
+            frame.size.width = bounds.right - bounds.left;
+            frame.size.height = bounds.bottom - bounds.top;
+
+//            printf( "   before frame convert (%g %g) (%g %g)\n", frame.origin.x, frame.origin.y,
+//                frame.size.width, frame.size.height );
+            
+            [inView->fWebView convertRect:*(NSRect*)&frame fromView:nil];
+
+//            printf( "   moving web view to (%g %g) (%g %g)\n", frame.origin.x, frame.origin.y,
+//                frame.size.width, frame.size.height );
+
+            [inView->fWebView setFrameOrigin: *(NSPoint*)&frame.origin];
+            [inView->fWebView setFrameSize: *(NSSize*)&frame.size];
+        }
+    }
+}
+
+//----------------------------------------------------------------------------------
+// SetFocusPart
+//----------------------------------------------------------------------------------
+//
+static OSStatus
+SetFocusPart(
+	HIWebView*				view,
+	ControlPartCode 		desiredFocus,
+	RgnHandle 				invalidRgn,
+	Boolean 				focusEverything,
+	ControlPartCode* 		actualFocus )
+{
+    NSView *	freshlyMadeFirstResponderView;
+    SInt32 		partCodeToReturn;
+
+    // Do what Carbon is telling us to do.
+    if ( desiredFocus == kControlFocusNoPart )
+	{
+        // Relinquish the keyboard focus.
+        RelinquishFocus( view, true ); //(autodisplay ? YES : NO));
+        freshlyMadeFirstResponderView = nil;
+        partCodeToReturn = kControlFocusNoPart;
+		//NSLog(@"Relinquished the key focus because we have no choice.");
+    }
+	else if ( desiredFocus == kControlFocusNextPart || desiredFocus == kControlFocusPrevPart )
+	{
+        BOOL goForward = (desiredFocus == kControlFocusNextPart );
+
+        // Advance the keyboard focus, maybe right off of this view.  Maybe a subview of this one already has the keyboard focus, maybe not.
+        freshlyMadeFirstResponderView = AdvanceFocus( view, goForward );
+        if (freshlyMadeFirstResponderView)
+            partCodeToReturn = desiredFocus;
+        else
+            partCodeToReturn = kControlFocusNoPart;
+        //NSLog(freshlyMadeFirstResponderView ? @"Advanced the key focus." : @"Relinquished the key focus.");
+    }
+	else
+	{
+		// What's this?
+                if (desiredFocus != kControlIndicatorPart) {
+                    check(false);
+                }
+		freshlyMadeFirstResponderView = nil;
+		partCodeToReturn = desiredFocus;
+    }
+
+	view->fFirstResponder = freshlyMadeFirstResponderView;
+
+	*actualFocus = partCodeToReturn;
+
+	// Done.
+	return noErr;
+}
+
+//----------------------------------------------------------------------------------
+// AdvanceFocus
+//----------------------------------------------------------------------------------
+//
+static NSView*
+AdvanceFocus( HIWebView* view, bool forward )
+{
+    NSResponder*		oldFirstResponder;
+    NSView*				currentKeyView;
+    NSView*				viewWeMadeFirstResponder;
+    
+    //	Focus on some part (subview) of this control (view).  Maybe
+	//	a subview of this one already has the keyboard focus, maybe not.
+	
+	oldFirstResponder = [view->fKitWindow firstResponder];
+
+	// If we tab out of our NSView, it will no longer be the responder
+	// when we get here. We'll try this trick for now. We might need to
+	// tag the view appropriately.
+
+	if ( view->fFirstResponder && ( (NSResponder*)view->fFirstResponder != oldFirstResponder ) )
+	{
+		return NULL;
+	}
+	
+	if ( [oldFirstResponder isKindOfClass:[NSView class]] )
+	{
+		NSView*		tentativeNewKeyView;
+
+        // Some view in this window already has the keyboard focus.  It better at least be a subview of this one.
+        NSView*	oldFirstResponderView = (NSView *)oldFirstResponder;
+        check( [oldFirstResponderView isDescendantOf:view->fWebView] );
+
+		if ( oldFirstResponderView != view->fFirstResponder
+			&& ![oldFirstResponderView isDescendantOf:view->fFirstResponder] )
+		{
+            // Despite our efforts to record what view we made the first responder
+			// (for use in the next paragraph) we couldn't keep up because the user
+			// has clicked in a text field to make it the key focus, instead of using
+			// the tab key.  Find a control on which it's reasonable to invoke
+			// -[NSView nextValidKeyView], taking into account the fact that
+			// NSTextFields always pass on first-respondership to a temporarily-
+			// contained NSTextView.
+
+			NSView *viewBeingTested;
+			currentKeyView = oldFirstResponderView;
+			viewBeingTested = currentKeyView;
+			while ( viewBeingTested != view->fWebView )
+			{
+				if ( [viewBeingTested isKindOfClass:[NSTextField class]] )
+				{
+					currentKeyView = viewBeingTested;
+					break;
+				}
+				else
+				{
+					viewBeingTested = [viewBeingTested superview];
+				}
+			}
+		}
+		else 
+		{
+			// We recorded which view we made into the first responder the
+			// last time the user hit the tab key, and nothing has invalidated
+			// our recorded value since.
+			
+			currentKeyView = view->fFirstResponder;
+		}
+
+        // Try to move on to the next or previous key view.  We use the laboriously
+		// recorded/figured currentKeyView instead of just oldFirstResponder as the
+		// jumping-off-point when searching for the next valid key view.  This is so
+		// we don't get fooled if we recently made some view the first responder, but
+		// it passed on first-responder-ness to some temporary subview.
+		
+        // You can't put normal views in a window with Carbon-control-wrapped views.
+		// Stuff like this would break.  M.P. Notice - 12/2/00
+
+        tentativeNewKeyView = forward ? [currentKeyView nextValidKeyView] : [currentKeyView previousValidKeyView];
+        if ( tentativeNewKeyView && [tentativeNewKeyView isDescendantOf:view->fWebView] )
+		{
+            // The user has tabbed to another subview of this control view.  Change the keyboard focus.
+            //NSLog(@"Tabbed to the next or previous key view.");
+
+            [view->fKitWindow makeFirstResponder:tentativeNewKeyView];
+            viewWeMadeFirstResponder = tentativeNewKeyView;
+        }
+		else
+		{
+            // The user has tabbed past the subviews of this control view.  The window is the first responder now.
+            //NSLog(@"Tabbed past the first or last key view.");
+            [view->fKitWindow makeFirstResponder:view->fKitWindow];
+            viewWeMadeFirstResponder = nil;
+        }
+    }
+	else
+	{
+        // No view in this window has the keyboard focus.  This view should
+		// try to select one of its key subviews.  We're not interested in
+		// the subviews of sibling views here.
+
+		//NSLog(@"No keyboard focus in window. Attempting to set...");
+
+		NSView *tentativeNewKeyView;
+		check(oldFirstResponder==fKitWindow);
+		if ( [view->fWebView acceptsFirstResponder] )
+			tentativeNewKeyView = view->fWebView;
+		else
+			tentativeNewKeyView = [view->fWebView nextValidKeyView];
+        if ( tentativeNewKeyView && [tentativeNewKeyView isDescendantOf:view->fWebView] )
+		{
+            // This control view has at least one subview that can take the keyboard focus.
+            if ( !forward )
+			{
+                // The user has tabbed into this control view backwards.  Find
+				// and select the last subview of this one that can take the
+				// keyboard focus.  Watch out for loops of valid key views.
+
+                NSView *firstTentativeNewKeyView = tentativeNewKeyView;
+                NSView *nextTentativeNewKeyView = [tentativeNewKeyView nextValidKeyView];
+                while ( nextTentativeNewKeyView 
+						&& [nextTentativeNewKeyView isDescendantOf:view->fWebView] 
+						&& nextTentativeNewKeyView!=firstTentativeNewKeyView)
+				{
+                    tentativeNewKeyView = nextTentativeNewKeyView;
+                    nextTentativeNewKeyView = [tentativeNewKeyView nextValidKeyView];
+                }
+
+            }
+
+            // Set the keyboard focus.
+            //NSLog(@"Tabbed into the first or last key view.");
+            [view->fKitWindow makeFirstResponder:tentativeNewKeyView];
+            viewWeMadeFirstResponder = tentativeNewKeyView;
+        }
+		else
+		{
+            // This control view has no subviews that can take the keyboard focus.
+            //NSLog(@"Can't tab into this view.");
+            viewWeMadeFirstResponder = nil;
+        }
+    }
+
+    // Done.
+    return viewWeMadeFirstResponder;
+}
+
+
+//----------------------------------------------------------------------------------
+// RelinquishFocus
+//----------------------------------------------------------------------------------
+//
+static void
+RelinquishFocus( HIWebView* view, bool inAutodisplay )
+{
+    NSResponder*  firstResponder;
+
+    // Apparently Carbon thinks that some subview of this control view has the keyboard focus,
+	// or we wouldn't be being asked to relinquish focus.
+
+	firstResponder = [view->fKitWindow firstResponder];
+	if ( [firstResponder isKindOfClass:[NSView class]] )
+	{
+		// Some subview of this control view really is the first responder right now.
+		check( [(NSView *)firstResponder isDescendantOf:view->fWebView] );
+
+		// Make the window the first responder, so that no view is the key view.
+        [view->fKitWindow makeFirstResponder:view->fKitWindow];
+
+		// 	If this control is not allowed to do autodisplay, don't let
+		//	it autodisplay any just-changed focus rings or text on the
+		//	next go around the event loop. I'm probably clearing more
+		//	dirty rects than I have to, but it doesn't seem to hurt in
+		//	the print panel accessory view case, and I don't have time
+		//	to figure out exactly what -[NSCell _setKeyboardFocusRingNeedsDisplay]
+		//	is doing when invoked indirectly from -makeFirstResponder up above.  M.P. Notice - 12/4/00
+
+		if ( !inAutodisplay )
+			[[view->fWebView opaqueAncestor] _clearDirtyRectsForTree];
+    }
+	else
+	{
+		//  The Cocoa first responder does not correspond to the Carbon
+		//	control that has the keyboard focus.  This can happen when
+		//	you've closed a dialog by hitting return in an NSTextView
+		//	that's a subview of this one; Cocoa closed the window, and
+		//	now Carbon is telling this control to relinquish the focus
+		//	as it's being disposed.  There's nothing to do.
+
+		check(firstResponder==window);
+	}
+}
+
+//----------------------------------------------------------------------------------
+// ActiveStateChanged
+//----------------------------------------------------------------------------------
+//
+static void
+ActiveStateChanged( HIWebView* view )
+{
+	if ( [view->fWebView respondsToSelector:@selector(setEnabled)] )
+	{
+		[(NSControl*)view->fWebView setEnabled: IsControlEnabled( view->fViewRef )];
+		HIViewSetNeedsDisplay( view->fViewRef, true );
+	}
+}
+
+
+//----------------------------------------------------------------------------------
+// ProcessCommand
+//----------------------------------------------------------------------------------
+//
+static OSStatus
+ProcessCommand( HIWebView* inView, const HICommand* inCommand )
+{
+	OSStatus		result = eventNotHandledErr;
+	NSResponder*	resp;
+	
+	resp = [inView->fKitWindow firstResponder];
+
+	if ( [resp isKindOfClass:[NSView class]] )
+	{
+		NSView*	respView = (NSView*)resp;
+
+		if ( respView == inView->fWebView
+			|| [respView isDescendantOf: inView->fWebView] )
+		{
+			switch ( inCommand->commandID )
+			{
+				case kHICommandCut:
+				case kHICommandCopy:
+				case kHICommandPaste:
+				case kHICommandClear:
+				case kHICommandSelectAll:
+					{
+						SEL selector = _NSSelectorForHICommand( inCommand );
+						if ( [respView respondsToSelector:selector] )
+						{
+							[respView performSelector:selector withObject:nil];
+							result = noErr;
+						}
+					}
+					break;
+			}
+		}
+	}
+	
+	return result;
+}
+
+//----------------------------------------------------------------------------------
+// UpdateCommandStatus
+//----------------------------------------------------------------------------------
+//
+static OSStatus
+UpdateCommandStatus( HIWebView* inView, const HICommand* inCommand )
+{
+	OSStatus		result = eventNotHandledErr;
+	MenuItemProxy* 	proxy = NULL;
+	NSResponder*	resp;
+	
+	resp = [inView->fKitWindow firstResponder];
+	
+	if ( [resp isKindOfClass:[NSView class]] )
+	{
+		NSView*	respView = (NSView*)resp;
+
+		if ( respView == inView->fWebView
+			|| [respView isDescendantOf: inView->fWebView] )
+		{
+			if ( inCommand->attributes & kHICommandFromMenu )
+			{
+				SEL selector = _NSSelectorForHICommand( inCommand );
+	
+				if ( selector )
+				{
+					if ( [resp respondsToSelector: selector] )
+					{
+						proxy = [[MenuItemProxy alloc] initWithAction: selector];
+						
+                        // Can't use -performSelector:withObject: here because the method we're calling returns BOOL, while
+                        // -performSelector:withObject:'s return value is assumed to be an id.
+                        BOOL (*validationFunction)(id, SEL, id) = (BOOL (*)(id, SEL, id))objc_msgSend;
+                        if (validationFunction(resp, @selector(validateUserInterfaceItem:), proxy))
+							EnableMenuItem( inCommand->menu.menuRef, inCommand->menu.menuItemIndex );
+						else
+							DisableMenuItem( inCommand->menu.menuRef, inCommand->menu.menuItemIndex );
+						
+						result = noErr;
+					}
+				}
+			}
+		}
+	}
+	
+	if ( proxy )
+		[proxy release];
+
+	return result;
+}
+
+// Blatantly stolen from AppKit and cropped a bit
+
+//----------------------------------------------------------------------------------
+// _NSSelectorForHICommand
+//----------------------------------------------------------------------------------
+//
+static SEL
+_NSSelectorForHICommand( const HICommand* inCommand )
+{
+    switch ( inCommand->commandID )
+	{
+        case kHICommandUndo: return @selector(undo:);
+        case kHICommandRedo: return @selector(redo:);
+        case kHICommandCut  : return @selector(cut:);
+        case kHICommandCopy : return @selector(copy:);
+        case kHICommandPaste: return @selector(paste:);
+        case kHICommandClear: return @selector(delete:);
+        case kHICommandSelectAll: return @selector(selectAll:);
+        default: return NULL;
+    }
+
+    return NULL;
+}
+
+
+//-----------------------------------------------------------------------------------
+//	HIWebViewEventHandler
+//-----------------------------------------------------------------------------------
+//	Our object's virtual event handler method. I'm not sure if we need this these days.
+//	We used to do various things with it, but those days are long gone...
+//
+static OSStatus
+HIWebViewEventHandler(
+	EventHandlerCallRef	inCallRef,
+	EventRef			inEvent,
+	void *				inUserData )
+{
+	OSStatus			result = eventNotHandledErr;
+	HIPoint				where;
+	OSType				tag;
+	void *				ptr;
+	Size				size;
+	UInt32				features;
+	RgnHandle			region = NULL;
+	ControlPartCode		part;
+	HIWebView*			view = (HIWebView*)inUserData;
+
+        // [NSApp setWindowsNeedUpdate:YES] must be called before events so that ActivateTSMDocument is called to set an active document. 
+        // Without an active document, TSM will use a default document which uses a bottom-line input window which we don't want.
+        [NSApp setWindowsNeedUpdate:YES];
+        
+	switch ( GetEventClass( inEvent ) )
+	{
+		case kEventClassHIObject:
+			switch ( GetEventKind( inEvent ) )
+			{
+				case kEventHIObjectConstruct:
+					{
+						HIObjectRef		object;
+
+						result = GetEventParameter( inEvent, kEventParamHIObjectInstance,
+								typeHIObjectRef, NULL, sizeof( HIObjectRef ), NULL, &object );
+						require_noerr( result, MissingParameter );
+						
+						// on entry for our construct event, we're passed the
+						// creation proc we registered with for this class.
+						// we use it now to create the instance, and then we
+						// replace the instance parameter data with said instance
+						// as type void.
+
+						view = HIWebViewConstructor( (HIViewRef)object );
+
+						if ( view )
+						{
+							SetEventParameter( inEvent, kEventParamHIObjectInstance,
+									typeVoidPtr, sizeof( void * ), &view ); 
+						}
+					}
+					break;
+				
+				case kEventHIObjectDestruct:
+					HIWebViewDestructor( view );
+					// result is unimportant
+					break;
+			}
+			break;
+
+		case kEventClassKeyboard:
+			{
+				NSEvent* kitEvent = WKCreateNSEventWithCarbonEvent(inEvent);
+				[view->fKitWindow sendSuperEvent:kitEvent];
+				[kitEvent release];
+				result = noErr;
+			}
+			break;
+
+		case kEventClassMouse:
+			switch ( GetEventKind( inEvent ) )
+			{
+				case kEventMouseUp:
+					result = MouseUp( view, inEvent );
+					break;
+				
+				case kEventMouseWheelMoved:
+					result = MouseWheelMoved( view, inEvent );
+					break;
+
+				case kEventMouseMoved:
+					result = MouseMoved( view, inEvent );
+					break;
+
+				case kEventMouseDragged:
+					result = MouseDragged( view, inEvent );
+					break;
+			}
+			break;
+
+		case kEventClassCommand:
+			{
+				HICommand		command;
+				
+				result = GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL,
+								sizeof( HICommand ), NULL, &command );
+				require_noerr( result, MissingParameter );
+				
+				switch ( GetEventKind( inEvent ) )
+				{
+					case kEventCommandProcess:
+						result = ProcessCommand( view, &command );
+						break;
+					
+					case kEventCommandUpdateStatus:
+						result = UpdateCommandStatus( view, &command );
+						break;
+				}
+			}
+			break;
+
+		case kEventClassControl:
+			switch ( GetEventKind( inEvent ) )
+			{
+				case kEventControlInitialize:
+					features = GetBehaviors();
+					SetEventParameter( inEvent, kEventParamControlFeatures, typeUInt32,
+							sizeof( UInt32 ), &features );
+					result = noErr;
+					break;
+					
+				case kEventControlDraw:
+					{
+						CGContextRef		context = NULL;
+						
+						GetEventParameter( inEvent, kEventParamRgnHandle, typeQDRgnHandle, NULL,
+								sizeof( RgnHandle ), NULL, &region );
+						GetEventParameter( inEvent, kEventParamCGContextRef, typeCGContextRef, NULL,
+								sizeof( CGContextRef ), NULL, &context );
+
+						Draw( view, region, context );
+
+						result = noErr;
+					}
+					break;
+				
+				case kEventControlHitTest:
+					GetEventParameter( inEvent, kEventParamMouseLocation, typeHIPoint, NULL,
+							sizeof( HIPoint ), NULL, &where );
+					part = HitTest( view, &where );
+					SetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, sizeof( ControlPartCode ), &part );
+					result = noErr;
+					break;
+					
+				case kEventControlGetPartRegion:
+					GetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, NULL,
+							sizeof( ControlPartCode ), NULL, &part );
+					GetEventParameter( inEvent, kEventParamControlRegion, typeQDRgnHandle, NULL,
+							sizeof( RgnHandle ), NULL, &region );
+					result = GetRegion( view, part, region );
+					break;
+				
+				case kEventControlGetData:
+					GetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, NULL, sizeof(ControlPartCode), NULL, &part);
+					GetEventParameter(inEvent, kEventParamControlDataTag, typeEnumeration, NULL, sizeof(OSType), NULL, &tag);
+					GetEventParameter(inEvent, kEventParamControlDataBuffer, typePtr, NULL, sizeof(Ptr), NULL, &ptr);
+					GetEventParameter(inEvent, kEventParamControlDataBufferSize, typeByteCount, NULL, sizeof(Size), NULL, &size);
+
+					if (tag == kControlKindTag) {
+						Size outSize;
+						result = noErr;
+
+						if (ptr) {
+							if (size != sizeof(ControlKind))
+								result = errDataSizeMismatch;
+							else
+								(*(ControlKind *)ptr) = GetKind();
+						}
+
+						outSize = sizeof(ControlKind);
+						SetEventParameter(inEvent, kEventParamControlDataBufferSize, typeByteCount, sizeof(Size), &outSize);
+					}
+
+					break;
+				
+				case kEventControlBoundsChanged:
+					{
+						HIRect		prevRect, currRect;
+						UInt32		attrs;
+						
+						GetEventParameter( inEvent, kEventParamAttributes, typeUInt32, NULL,
+								sizeof( UInt32 ), NULL, &attrs );
+						GetEventParameter( inEvent, kEventParamOriginalBounds, typeHIRect, NULL,
+								sizeof( HIRect ), NULL, &prevRect );
+						GetEventParameter( inEvent, kEventParamCurrentBounds, typeHIRect, NULL,
+								sizeof( HIRect ), NULL, &currRect );
+
+						BoundsChanged( view, attrs, &prevRect, &currRect );
+						result = noErr;
+					}
+					break;
+				
+				case kEventControlActivate:
+					ActiveStateChanged( view );
+					result = noErr;
+					break;
+					
+				case kEventControlDeactivate:
+					ActiveStateChanged( view );
+					result = noErr;
+					break;
+															
+				case kEventControlOwningWindowChanged:
+					{
+						WindowRef		fromWindow, toWindow;
+						
+						result = GetEventParameter( inEvent, kEventParamControlOriginalOwningWindow, typeWindowRef, NULL,
+										sizeof( WindowRef ), NULL, &fromWindow );
+						require_noerr( result, MissingParameter );
+
+						result = GetEventParameter( inEvent, kEventParamControlCurrentOwningWindow, typeWindowRef, NULL,
+										sizeof( WindowRef ), NULL, &toWindow );
+						require_noerr( result, MissingParameter );
+
+						OwningWindowChanged( view, fromWindow, toWindow );
+						
+						result = noErr;
+					}
+					break;
+                                    
+				case kEventControlClick:
+					result = Click( view, inEvent );
+					break;
+                                    
+				case kEventControlContextualMenuClick:
+					result = ContextMenuClick( view, inEvent );
+					break;
+                                    
+				case kEventControlSetFocusPart:
+					{
+						ControlPartCode		desiredFocus;
+						RgnHandle			invalidRgn;
+						Boolean				focusEverything;
+						ControlPartCode		actualFocus;
+						
+						result = GetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, NULL,
+										sizeof( ControlPartCode ), NULL, &desiredFocus ); 
+						require_noerr( result, MissingParameter );
+						
+						GetEventParameter( inEvent, kEventParamControlInvalRgn, typeQDRgnHandle, NULL,
+								sizeof( RgnHandle ), NULL, &invalidRgn );
+
+						focusEverything = false; // a good default in case the parameter doesn't exist
+
+						GetEventParameter( inEvent, kEventParamControlFocusEverything, typeBoolean, NULL,
+								sizeof( Boolean ), NULL, &focusEverything );
+
+						result = SetFocusPart( view, desiredFocus, invalidRgn, focusEverything, &actualFocus );
+						
+						if ( result == noErr )
+							verify_noerr( SetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode,
+									sizeof( ControlPartCode ), &actualFocus ) );
+					}
+					break;
+				
+				// some other kind of Control event
+				default:
+					break;
+			}
+			break;
+			
+		// some other event class
+		default:
+			break;
+	}
+
+MissingParameter:
+	return result;
+}
+
+
+static void UpdateObserver(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info);
+
+static void
+StartUpdateObserver( HIWebView* view )
+{
+	CFRunLoopObserverContext	context;
+	CFRunLoopObserverRef		observer;
+    CFRunLoopRef				mainRunLoop;
+    
+    check( view->fIsComposited == false );
+    check( view->fUpdateObserver == NULL );
+
+	context.version = 0;
+	context.info = view;
+	context.retain = NULL;
+	context.release = NULL;
+	context.copyDescription = NULL;
+
+    mainRunLoop = (CFRunLoopRef)GetCFRunLoopFromEventLoop( GetMainEventLoop() );
+	observer = CFRunLoopObserverCreate( NULL, kCFRunLoopEntry | kCFRunLoopBeforeWaiting, true, 0, UpdateObserver, &context );
+	CFRunLoopAddObserver( mainRunLoop, observer, kCFRunLoopCommonModes ); 
+
+    view->fUpdateObserver = observer;
+    
+//    printf( "Update observer started\n" );
+}
+
+static void
+StopUpdateObserver( HIWebView* view )
+{
+    check( view->fIsComposited == false );
+    check( view->fUpdateObserver != NULL );
+
+    CFRunLoopObserverInvalidate( view->fUpdateObserver );
+    CFRelease( view->fUpdateObserver );
+    view->fUpdateObserver = NULL;
+
+//    printf( "Update observer removed\n" );
+}
+
+static void 
+UpdateObserver( CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info )
+{
+	HIWebView*			view = (HIWebView*)info;
+    RgnHandle			region = NewRgn();
+    
+//    printf( "Update observer called\n" );
+
+    if ( region )
+    {
+        GetWindowRegion( GetControlOwner( view->fViewRef ), kWindowUpdateRgn, region );
+        
+        if ( !EmptyRgn( region ) )
+        {
+            RgnHandle		ourRgn = NewRgn();
+            Rect			rect;
+            
+            GetWindowBounds( GetControlOwner( view->fViewRef ), kWindowStructureRgn, &rect );
+            
+//            printf( "Update region is non-empty\n" );
+            
+            if ( ourRgn )
+            {
+                Rect		rect;
+                GrafPtr		savePort, port;
+                Point		offset = { 0, 0 };
+                
+                port = GetWindowPort( GetControlOwner( view->fViewRef ) );
+                
+                GetPort( &savePort );
+                SetPort( port );
+                
+                GlobalToLocal( &offset );
+                OffsetRgn( region, offset.h, offset.v );
+
+                GetControlBounds( view->fViewRef, &rect );
+                RectRgn( ourRgn, &rect );
+                
+//                printf( "our control is at %d %d %d %d\n",
+//                        rect.top, rect.left, rect.bottom, rect.right );
+                
+                GetRegionBounds( region, &rect );
+//                printf( "region is at %d %d %d %d\n",
+//                        rect.top, rect.left, rect.bottom, rect.right );
+
+                SectRgn( ourRgn, region, ourRgn );
+                
+                GetRegionBounds( ourRgn, &rect );
+//                printf( "intersection is  %d %d %d %d\n",
+//                       rect.top, rect.left, rect.bottom, rect.right );
+                if ( !EmptyRgn( ourRgn ) )
+                {
+                    RgnHandle	saveVis = NewRgn();
+                    
+//                    printf( "looks like we should draw\n" );
+
+                    if ( saveVis )
+                    {
+//                        RGBColor	kRedColor = { 0xffff, 0, 0 };
+                        
+                        GetPortVisibleRegion( GetWindowPort( GetControlOwner( view->fViewRef ) ), saveVis );
+                        SetPortVisibleRegion( GetWindowPort( GetControlOwner( view->fViewRef ) ), ourRgn );
+                        
+//                        RGBForeColor( &kRedColor );
+//                        PaintRgn( ourRgn );
+//                        QDFlushPortBuffer( port, NULL );
+//                        Delay( 15, NULL );
+
+                        Draw1Control( view->fViewRef );
+                        ValidWindowRgn( GetControlOwner( view->fViewRef ), ourRgn );
+                        
+                        SetPortVisibleRegion( GetWindowPort( GetControlOwner( view->fViewRef ) ), saveVis );
+                        DisposeRgn( saveVis );
+                    }
+                }
+
+                SetPort( savePort );
+                
+                DisposeRgn( ourRgn );
+            }
+        }
+        
+        DisposeRgn( region );
+    }
+}
+
+#endif