/Tools/NativeHost/WebWindow.m
http://github.com/cacaodev/cappuccino · Objective C · 515 lines · 350 code · 135 blank · 30 comment · 50 complexity · bbcb2319f694916f4512c1b4f5181c9c MD5 · raw file
- //
- // WebWindow.m
- // NativeHost
- //
- // Created by Francisco Tolmasky on 10/18/09.
- // Copyright 2009 280 North, Inc.. All rights reserved.
- //
- #import "WebWindow.h"
- static NSMutableArray * DisabledWindows;
- CFMachPortRef tap_port;
- CGEventRef headTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
- {
- // It's dangerous to fail in this code: could disable mousedown system-wide. So just try catch it all.
- @try
- {
- if (type == kCGEventLeftMouseDown)
- {
- CGPoint location = CGEventGetLocation(event);
- NSPoint NSLocation = NSMakePoint(location.x, location.y);
- for (NSWindow * window in [NSApp windows])
- {
- if ([window isKindOfClass:[WebWindow class]] && ![(WebWindow *)window hitTest:NSLocation])
- {
- [window setIgnoresMouseEvents:YES];
- [window performSelector:@selector(setIgnoresMouseEvents:) withObject:NO afterDelay:1.0];
-
- [DisabledWindows addObject:window];
- }
- }
- }
- else if (type == kCGEventTapDisabledByTimeout)
- CGEventTapEnable(tap_port, YES);
- }
- @catch (NSException * anException)
- {
- }
- return event;
- }
- @interface WebWindowContentView : NSView
- {
- }
- @end
- @implementation WebWindow
- + (void)enableAllWindows
- {
- [DisabledWindows makeObjectsPerformSelector:@selector(stopIgnoringMouseEvents)];
- [DisabledWindows removeAllObjects];
- }
- + (void)initialize
- {
- if (self != [WebWindow class])
- return;
- DisabledWindows = [[NSMutableArray alloc] init];
- //| CGEventMaskBit(kCGEventTapDisabledByTimeout)
- tap_port = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap,
- kCGEventTapOptionDefault,
- CGEventMaskBit(kCGEventLeftMouseDown),
- headTapCallback, NULL);
- if (NULL == tap_port)
- {
- fprintf(stderr, "Error creating event tap\n");
- return;
- }
- /* Create a run loop source from the tap port, add it to my run loop
- * and start executing the loop
- */
- CFRunLoopSourceRef tap_source = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap_port, 0);
- if (NULL == tap_source)
- {
- fprintf(stderr, "Error converting port to run loop source\n");
- if (tap_port != NULL)
- CFRelease(tap_port);
- return;
- }
- CFRunLoopAddSource(CFRunLoopGetCurrent(), tap_source, kCFRunLoopCommonModes);
- }
- - (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)windowStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)shouldDeferCreation
- {
- self = [super initWithContentRect:aContentRect styleMask:NSBorderlessWindowMask backing:aBufferingType defer:shouldDeferCreation];
- if (self)
- {
- id delegate = [NSApp delegate];
- shadowView = [[WebWindowContentView alloc] init];
- [self setContentView:shadowView];
- webView = [[WebView alloc] initWithFrame:NSZeroRect];
- [webView setDrawsBackground:NO];
- [webView setUIDelegate:delegate];
- [webView setFrameLoadDelegate:delegate];
- [webView setResourceLoadDelegate:delegate];
- [webView setPolicyDelegate:delegate];
- [webView setShouldCloseWithWindow:YES];
- [shadowView addSubview:webView];
- [self setBackgroundColor:[NSColor clearColor]];
- [self setOpaque:NO];
- [self setIgnoresMouseEvents:NO];
- [self setReleasedWhenClosed:YES];
- [super setHasShadow:NO];
- }
- return self;
- }
- - (void)setFrame:(NSRect)aFrame display:(BOOL)shouldDisplay
- {
- [webView setFrame:NSMakeRect(33.0, 33.0, NSWidth(aFrame), NSHeight(aFrame))];
- [super setFrame:NSInsetRect(aFrame, -33.0, -33.0) display:YES];
- }
- - (void)dealloc
- {
- [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResizeNotification object:self];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidBecomeKeyNotification object:self];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidResignKeyNotification object:self];
- [shadowView release];
- [webView release];
- [super dealloc];
- }
- - (BOOL)canBecomeKeyWindow
- {
- // Necessary since this apparently returns NO for borderless windows.
- return YES;
- }
- - (NSView *)webHitTest:(NSPoint)aPoint
- {
- NSPoint locationInWebView = [[self contentView] convertPoint:aPoint fromView:nil];
- return [(NSView *)[self contentView] hitTest:locationInWebView];
- }
- - (void)sendEvent:(NSEvent *)anEvent
- {
- NSInteger type = [anEvent type];
- if (type == NSLeftMouseDown)
- {
- NSView * view = [self webHitTest:[anEvent locationInWindow]];
- leftMouseDownView = view;
- [view mouseDown:anEvent];
- }
- else if (type == NSLeftMouseDragged)
- [leftMouseDownView mouseDragged:anEvent];
- else if (type == NSLeftMouseUp)
- [leftMouseDownView mouseUp:anEvent];
- else if (type == NSRightMouseDown)
- {
- NSView * view = [self webHitTest:[anEvent locationInWindow]];
- rightMouseDownView = view;
- [view rightMouseDown:anEvent];
- }
- else if (type == NSRightMouseDragged)
- [rightMouseDownView rightMouseDragged:anEvent];
- else if (type == NSRightMouseUp)
- [rightMouseDownView rightMouseUp:anEvent];
- else
- [super sendEvent:anEvent];
- // FIXME: other
- }
- // Override this to avoid the beep from unhandled events.
- - (void)keyDown:(NSEvent *)anEvent
- {
- }
- + (WebWindow *)webWindow
- {
- return [[WebWindow alloc] initWithContentRect:NSZeroRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
- }
- - (WebView *)webView
- {
- return webView;
- }
- - (void)updateShadow
- {
- [super setHasShadow:hasShadow && shadowStyle == CPCustomWindowShadowStyle];
- [shadowView setNeedsDisplay:YES];
- }
- - (BOOL)hasShadow
- {
- return hasShadow;
- }
- - (void)setHasShadow:(BOOL)shouldHaveShadow
- {
- if (hasShadow == shouldHaveShadow)
- return;
- hasShadow = shouldHaveShadow;
- [self updateShadow];
- }
- - (CPWindowShadowStyle)shadowStyle
- {
- return shadowStyle;
- }
- - (void)setShadowStyle:(CPWindowShadowStyle)aStyle
- {
- if (shadowStyle == aStyle)
- return;
- shadowStyle = aStyle;
- [self updateShadow];
- }
- - (BOOL)hitTest:(NSPoint)aPoint
- {
- NSInteger windowNumber = [[[webView windowScriptObject] valueForKey:@"cpWindowNumber"] intValue];
- #if LOGGING
- WebScriptObject * frame = [[[NSApp delegate] windowScriptObject] evaluateWebScript:[NSString stringWithFormat:@"(objj_msgSend(objj_msgSend(CPApp, \"windowWithWindowNumber:\", %d), \"frame\"))", windowNumber]],
- * origin = [frame valueForKey:@"origin"],
- * size = [frame valueForKey:@"size"];
- NSLog(@"(%f, %f) in { %f, %f, %f, %f }", aPoint.x, aPoint.y, [[origin valueForKey:@"x"] floatValue], [[origin valueForKey:@"y"] floatValue], [[size valueForKey:@"width"] floatValue], [[size valueForKey:@"height"] floatValue]);
- #endif
- return [[[[NSApp delegate] windowScriptObject] evaluateWebScript:[NSString stringWithFormat:@"(CGRectContainsPoint(objj_msgSend(objj_msgSend(CPApp, \"windowWithWindowNumber:\", %d), \"frame\"), CGPointMake(%f, %f)))", windowNumber, aPoint.x, aPoint.y]] boolValue];
- }
- - (void)stopIgnoringMouseEvents
- {
- [self setIgnoresMouseEvents:NO];
- }
- - (void)becomeKeyWindow
- {
- [super becomeKeyWindow];
- [self updateShadow];
- }
- - (void)resignKeyWindow
- {
- [super resignKeyWindow];
- [self updateShadow];
- }
- @end
- @interface NSImage (Additions)
- - (void)drawInRect:(NSRect)aRect slices:(CGFloat [])slices;
- @end
- @implementation NSImage (Additions)
- - (void)drawInRect:(NSRect)aRect slices:(CGFloat [])slices
- {
- NSRect imageBounds = NSMakeRect(0.0, 0.0, [self size].width, [self size].height);
- [self drawInRect:NSMakeRect(0.0, 0.0, slices[0], slices[1])
- fromRect:NSMakeRect(0.0, 0.0, slices[0], slices[1])
- operation:NSCompositeSourceOver
- fraction:1.0];
- [self drawInRect:NSMakeRect(NSMaxX(aRect) - slices[2], 0.0, slices[2], slices[1])
- fromRect:NSMakeRect(NSMaxX(imageBounds) - slices[2], 0.0, slices[2], slices[1])
- operation:NSCompositeSourceOver
- fraction:1.0];
- [self drawInRect:NSMakeRect(0.0, NSMaxY(aRect) - slices[3], slices[0], slices[3])
- fromRect:NSMakeRect(0.0, NSMaxY(imageBounds) - slices[3], slices[0], slices[3])
- operation:NSCompositeSourceOver
- fraction:1.0];
- [self drawInRect:NSMakeRect(NSMaxX(aRect) - slices[2], NSMaxY(aRect) - slices[3], slices[2], slices[3])
- fromRect:NSMakeRect(NSMaxX(imageBounds) - slices[2], NSMaxY(imageBounds) - slices[3], slices[2], slices[3])
- operation:NSCompositeSourceOver
- fraction:1.0];
- [self drawInRect:NSMakeRect(slices[0], 0.0, NSWidth(aRect) - slices[0] - slices[2], slices[1])
- fromRect:NSMakeRect(slices[0], 0.0, 1.0, slices[1])
- operation:NSCompositeSourceOver
- fraction:1.0];
- [self drawInRect:NSMakeRect(0.0, slices[1], slices[0], NSHeight(aRect) - slices[1] - slices[3])
- fromRect:NSMakeRect(0.0, slices[1], slices[0], 1.0)
- operation:NSCompositeSourceOver
- fraction:1.0];
- [self drawInRect:NSMakeRect(NSMaxX(aRect) - slices[2], slices[1], slices[2], NSHeight(aRect) - slices[1] - slices[3])
- fromRect:NSMakeRect(NSMaxX(imageBounds) - slices[2], slices[1], slices[2], 1.0)
- operation:NSCompositeSourceOver
- fraction:1.0];
- [self drawInRect:NSMakeRect(slices[0], NSMaxY(aRect) - slices[3], NSWidth(aRect) - slices[0] - slices[2], slices[3])
- fromRect:NSMakeRect(slices[0], NSMaxY(imageBounds) - slices[3], 1.0, slices[3])
- operation:NSCompositeSourceOver
- fraction:1.0];
- }
- @end
- @implementation WebWindowContentView : NSView
- {
- }
- static float OUTlINE_HORIZONTAL_INSET = 33.0;
- static float OUTlINE_VERTICAL_INSET = 33.0;
- - (void)drawStandardActiveShadowInRect:(NSRect)aRect
- {
- CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
- CGRect bounds = CGRectInset(*(CGRect *)&aRect, OUTlINE_HORIZONTAL_INSET - 0.5, OUTlINE_VERTICAL_INSET - 0.5);
- CGColorRef shadowColor = CGColorCreateGenericGray(0.0, 0.8);
- CGContextSetShadowWithColor (context, CGSizeMake(0.0, -10.0), 100.0, shadowColor);
- CGColorRelease(shadowColor);
- CGColorRef fillColor = CGColorCreateGenericGray(1.0, 1.0);
- CGColorRef strokeColor = CGColorCreateGenericGray(0.0, 0.2);
- CGContextSetFillColorWithColor(context, fillColor);
- CGContextSetStrokeColorWithColor(context, strokeColor);
- CGColorRelease(fillColor);
- CGColorRelease(strokeColor);
- CGContextBeginPath(context);
- CGContextAddArc(context, CGRectGetMinX(bounds) + 5.0, CGRectGetMaxY(bounds) - 5.0, 5.0, M_PI, M_PI_2, YES);
- CGContextAddArc(context, CGRectGetMaxX(bounds) - 5.0, CGRectGetMaxY(bounds) - 5.0, 5.0, M_PI_2, 0, YES);
- CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
- CGContextAddLineToPoint(context, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
- CGContextClosePath(context);
- CGContextDrawPath(context, kCGPathFillStroke);
- }
- - (void)drawStandardInactiveShadowInRect:(NSRect)aRect
- {
- CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
- CGRect bounds = CGRectInset(*(CGRect *)&aRect, OUTlINE_HORIZONTAL_INSET - 0.5, OUTlINE_VERTICAL_INSET - 0.5);
- CGColorRef shadowColor = CGColorCreateGenericGray(0.0, 0.5);
- CGContextSetShadowWithColor (context, CGSizeMake(0.0, -10.0), 40.0, shadowColor);
- CGColorRelease(shadowColor);
- CGColorRef fillColor = CGColorCreateGenericGray(1.0, 1.0);
- CGColorRef strokeColor = CGColorCreateGenericGray(0.0, 0.2);
- CGContextSetFillColorWithColor(context, fillColor);
- CGContextSetStrokeColorWithColor(context, strokeColor);
- CGColorRelease(fillColor);
- CGColorRelease(strokeColor);
- CGContextBeginPath(context);
- CGContextAddArc(context, CGRectGetMinX(bounds) + 5.0, CGRectGetMaxY(bounds) - 5.0, 5.0, M_PI, M_PI_2, YES);
- CGContextAddArc(context, CGRectGetMaxX(bounds) - 5.0, CGRectGetMaxY(bounds) - 5.0, 5.0, M_PI_2, 0, YES);
- CGContextAddLineToPoint(context, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
- CGContextAddLineToPoint(context, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
- CGContextClosePath(context);
- CGContextDrawPath(context, kCGPathFillStroke);
- }
- - (void)drawMenuShadowInRect:(NSRect)aRect
- {
- CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
- CGRect bounds = CGRectInset(*(CGRect *)&aRect, OUTlINE_HORIZONTAL_INSET - 0.5, OUTlINE_VERTICAL_INSET - 0.5);
- CGColorRef shadowColor = CGColorCreateGenericGray(0.0, 0.5);
- CGContextSetShadowWithColor (context, CGSizeMake(0.0, -10.0), 30.0, shadowColor);
- CGColorRelease(shadowColor);
- CGColorRef fillColor = CGColorCreateGenericGray(1.0, 1.0);
- CGColorRef strokeColor = CGColorCreateGenericGray(0.0, 0.2);
- CGContextSetFillColorWithColor(context, fillColor);
- CGContextSetStrokeColorWithColor(context, strokeColor);
- CGColorRelease(fillColor);
- CGColorRelease(strokeColor);
- CGContextBeginPath(context);
- CGContextAddArc(context, CGRectGetMinX(bounds) + 3.0, CGRectGetMaxY(bounds) - 3.0, 2.0, M_PI, M_PI_2, YES);
- CGContextAddArc(context, CGRectGetMaxX(bounds) - 3.0, CGRectGetMaxY(bounds) - 3.0, 2.0, M_PI_2, 0, YES);
- CGContextAddArc(context, CGRectGetMaxX(bounds) - 3.0, CGRectGetMinY(bounds) + 3.0, 2.0, 0, 3 * M_PI_2, YES);
- CGContextAddArc(context, CGRectGetMinX(bounds) + 3.0, CGRectGetMinY(bounds) + 3.0, 2.0, 3 * M_PI_2, M_PI, YES);
- CGContextClosePath(context);
- CGContextDrawPath(context, kCGPathFill);//Stroke);
- /*
- CGContextBeginPath(context);
- CGContextAddArc(context, CGRectGetMinX(bounds) + 3.0, CGRectGetMaxY(bounds) - 3.0, 2.0, M_PI, M_PI_2, YES);
- CGContextAddArc(context, CGRectGetMaxX(bounds) - 3.0, CGRectGetMaxY(bounds) - 3.0, 2.0, M_PI_2, 0, YES);
- CGContextAddArc(context, CGRectGetMaxX(bounds) - 3.0, CGRectGetMinY(bounds) + 3.0, 2.0, 0, 3 * M_PI_2, YES);
- CGContextAddArc(context, CGRectGetMinX(bounds) + 3.0, CGRectGetMinY(bounds) + 3.0, 2.0, 3 * M_PI_2, M_PI, YES);
- CGContextClosePath(context);
- CGContextSetFillColorWithColor(context, CGColorGetConstantColor(kCGColorClear));
- CGContextSetBlendMode(context, kCGBlendModeCopy);
- CGContextDrawPath(context, kCGPathFill);
- */
- }
- - (NSImage *)shadowImageWithSelector:(SEL)aSelector
- {
- static NSMutableDictionary * images = nil;
- if (!images)
- images = [[NSMutableDictionary alloc] init];
- NSString * name = NSStringFromSelector(aSelector);
- NSImage * image = [images objectForKey:name];
- if (!image)
- {
- image = [[NSImage alloc] initWithSize:NSMakeSize(100.0, 100.0)];
- [image lockFocus];
- objc_msgSend(self, aSelector, NSMakeRect(0.0, 0.0, 100.0, 100.0));
- [image unlockFocus];
- [images setObject:image forKey:name];
- [image release];
- }
- return image;
- }
- - (void)drawShadowWithSelector:(SEL)aSelector inRect:(NSRect)aRect
- {
- CGFloat slices[] = { 40.0, 49.0, 40.0, 49.0 };
- if (NSWidth(aRect) > 100.0 || NSHeight(aRect) > 100.0)
- [[self shadowImageWithSelector:aSelector] drawInRect:aRect slices:slices];
- else
- objc_msgSend(self, aSelector, aRect);
- }
- - (void)drawRect:(NSRect)aRect
- {
- WebWindow * window = (WebWindow *)[self window];
- NSRect bounds = [self bounds];
- if (![window hasShadow])
- return;
- if ([window shadowStyle] == CPStandardWindowShadowStyle)
- if ([window isKeyWindow])
- return [self drawShadowWithSelector:@selector(drawStandardActiveShadowInRect:) inRect:bounds];
- else
- return [self drawShadowWithSelector:@selector(drawStandardInactiveShadowInRect:) inRect:bounds];
- if ([window shadowStyle] == CPMenuWindowShadowStyle)
- return [self drawShadowWithSelector:@selector(drawMenuShadowInRect:) inRect:bounds];
- }
- @end