From 342b086650e6cba047b6a068d68143ae8557d9be Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Thu, 5 Nov 2009 21:59:42 +0000 Subject: [PATCH] Finished non-Cycript WebCycript lock screen. --- webcycript/CydgetCentral.plist | 2 +- webcycript/LockScreen.mm | 624 +++++++++++++++++++++++++++++++++ webcycript/control | 2 +- webcycript/makefile | 2 +- 4 files changed, 627 insertions(+), 3 deletions(-) diff --git a/webcycript/CydgetCentral.plist b/webcycript/CydgetCentral.plist index c215f0c..c96cf0f 100644 --- a/webcycript/CydgetCentral.plist +++ b/webcycript/CydgetCentral.plist @@ -1,4 +1,4 @@ Plugin = "WebCycriptLockScreen"; Configuration = { - Site = "http://www.cydget.org/central/"; + Homepage = "http://www.cydget.org/central/"; }; diff --git a/webcycript/LockScreen.mm b/webcycript/LockScreen.mm index e74e7d2..f919b52 100644 --- a/webcycript/LockScreen.mm +++ b/webcycript/LockScreen.mm @@ -40,8 +40,42 @@ #import #import #import + #import +#import +// XXX: fix the minimum requirement +extern NSString * const kCAFilterNearest; + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#import +#import + +#include +#include + +#include +#include + +@interface WebView (UICaboodle) +- (void) setScriptDebugDelegate:(id)delegate; +- (void) _setFormDelegate:(id)delegate; +- (void) _setUIKitDelegate:(id)delegate; +- (void) setWebMailDelegate:(id)delegate; +- (void) _setLayoutInterval:(float)interval; +@end + #define _transient #define _forever for (;;) @@ -53,12 +87,602 @@ _disused static unsigned trace_; ); \ } while (false) +@protocol CydgetController +- (NSDictionary *) currentConfiguration; +@end + +static Class $CydgetController(objc_getClass("CydgetController")); + +@interface NSString (UIKit) +- (NSString *) stringByAddingPercentEscapes; +@end + +@implementation UIWebDocumentView (WebCycript) + +- (void) _setScrollerOffset:(CGPoint)offset { + UIScroller *scroller([self _scroller]); + + CGSize size([scroller contentSize]); + CGSize bounds([scroller bounds].size); + + CGPoint max; + max.x = size.width - bounds.width; + max.y = size.height - bounds.height; + + // wtf Apple?! + if (max.x < 0) + max.x = 0; + if (max.y < 0) + max.y = 0; + + offset.x = offset.x < 0 ? 0 : offset.x > max.x ? max.x : offset.x; + offset.y = offset.y < 0 ? 0 : offset.y > max.y ? max.y : offset.y; + + [scroller setOffset:offset]; +} + +@end + +/* WebCycript Delegate {{{ */ +@interface WebCycriptDelegate : NSObject { + _transient volatile id delegate_; +} + +- (void) setDelegate:(id)delegate; +- (id) initWithDelegate:(id)delegate; +@end + +@implementation WebCycriptDelegate + +- (void) setDelegate:(id)delegate { + delegate_ = delegate; +} + +- (id) initWithDelegate:(id)delegate { + delegate_ = delegate; + return self; +} + +- (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame { + if (delegate_ != nil) + return [delegate_ webView:sender didClearWindowObject:window forFrame:frame]; +} + +- (void) webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame { + if (delegate_ != nil) + return [delegate_ webView:sender didCommitLoadForFrame:frame]; +} + +- (void) webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { + if (delegate_ != nil) + return [delegate_ webView:sender didFailLoadWithError:error forFrame:frame]; +} + +- (void) webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { + if (delegate_ != nil) + return [delegate_ webView:sender didFailProvisionalLoadWithError:error forFrame:frame]; +} + +- (void) webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame { + if (delegate_ != nil) + return [delegate_ webView:sender didFinishLoadForFrame:frame]; +} + +/*- (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame { + if (delegate_ != nil) + return [delegate_ webView:sender didReceiveTitle:title forFrame:frame]; +}*/ + +- (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame { + if (delegate_ != nil) + return [delegate_ webView:sender didStartProvisionalLoadForFrame:frame]; +} + +/*- (void) webView:(WebView *)sender resource:(id)identifier didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)source { + if (delegate_ != nil) + return [delegate_ webView:sender resource:identifier didReceiveAuthenticationChallenge:challenge fromDataSource:source]; +}*/ + +/*- (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)source { + if (delegate_ != nil) + return [delegate_ webView:sender resource:identifier willSendRequest:request redirectResponse:redirectResponse fromDataSource:source]; + return nil; +}*/ + +- (IMP) methodForSelector:(SEL)sel { + if (IMP method = [super methodForSelector:sel]) + return method; + fprintf(stderr, "methodForSelector:[%s] == NULL\n", sel_getName(sel)); + return NULL; +} + +- (BOOL) respondsToSelector:(SEL)sel { + if ([super respondsToSelector:sel]) + return YES; + // XXX: WebThreadCreateNSInvocation returns nil + //fprintf(stderr, "[%s]R?%s\n", class_getName(self->isa), sel_getName(sel)); + return delegate_ == nil ? NO : [delegate_ respondsToSelector:sel]; +} + +- (NSMethodSignature *) methodSignatureForSelector:(SEL)sel { + if (NSMethodSignature *method = [super methodSignatureForSelector:sel]) + return method; + //fprintf(stderr, "[%s]S?%s\n", class_getName(self->isa), sel_getName(sel)); + if (delegate_ != nil) + if (NSMethodSignature *sig = [delegate_ methodSignatureForSelector:sel]) + return sig; + // XXX: I fucking hate Apple so very very bad + return [NSMethodSignature signatureWithObjCTypes:"v@:"]; +} + +- (void) forwardInvocation:(NSInvocation *)inv { + SEL sel = [inv selector]; + if (delegate_ != nil && [delegate_ respondsToSelector:sel]) + [inv invokeWithTarget:delegate_]; +} + +@end +/* }}} */ + @interface WebCydgetLockScreenView : UIView { + WebCycriptDelegate *indirect_; + UIProgressIndicator *indicator_; + UIScroller *scroller_; + UIWebDocumentView *document_; + + float width_; + CGSize size_; + bool editing_; + + NSNumber *confirm_; + + NSMutableSet *loading_; + bool error_; + bool reloading_; } @end @implementation WebCydgetLockScreenView + +//#include "UICaboodle/UCInternal.h" + +- (void) dealloc { +_trace(); + WebThreadLock(); + + WebView *webview([document_ webView]); + [webview setFrameLoadDelegate:nil]; + [webview setResourceLoadDelegate:nil]; + [webview setUIDelegate:nil]; + [webview setScriptDebugDelegate:nil]; + [webview setPolicyDelegate:nil]; + + /* XXX: these are set by UIWebDocumentView + [webview setDownloadDelegate:nil]; + [webview _setFormDelegate:nil]; + [webview _setUIKitDelegate:nil]; + [webview setEditingDelegate:nil];*/ + + /* XXX: no one sets this, ever + [webview setWebMailDelegate:nil];*/ + + [document_ setDelegate:nil]; + [document_ setGestureDelegate:nil]; + [document_ setFormEditingDelegate:nil]; + [document_ setInteractionDelegate:nil]; + + [indirect_ setDelegate:nil]; + + [webview close]; + [document_ release]; + + [indirect_ release]; + + WebThreadUnlock(); + + [scroller_ setDelegate:nil]; + + if (confirm_ != nil) + [confirm_ release]; + + [scroller_ release]; + [indicator_ release]; + [super dealloc]; +} + ++ (float) defaultWidth { + return 980; +} + +- (void) _setTileDrawingEnabled:(BOOL)enabled { + //[document_ setTileDrawingEnabled:enabled]; +} + +- (void) willStartGesturesInView:(UIView *)view forEvent:(GSEventRef)event { + [self _setTileDrawingEnabled:NO]; +} + +- (void) didFinishGesturesInView:(UIView *)view forEvent:(GSEventRef)event { + [self _setTileDrawingEnabled:YES]; + [document_ redrawScaledDocument]; +} + +- (void) setViewportWidth:(float)width { + width_ = width != 0 ? width : [[self class] defaultWidth]; + [document_ setViewportSize:CGSizeMake(width_, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10]; +} + +- (void) scrollerWillStartDragging:(UIScroller *)scroller { + [self _setTileDrawingEnabled:NO]; +} + +- (void) scrollerDidEndDragging:(UIScroller *)scroller willSmoothScroll:(BOOL)smooth { + [self _setTileDrawingEnabled:YES]; +} + +- (void) scrollerDidEndDragging:(UIScroller *)scroller { + [self _setTileDrawingEnabled:YES]; +} + +- (void) loadRequest:(NSURLRequest *)request { + error_ = false; + + WebThreadLock(); + [document_ loadRequest:request]; + WebThreadUnlock(); +} + +- (void) loadURL:(NSURL *)url cachePolicy:(NSURLRequestCachePolicy)policy { + [self loadRequest:[NSURLRequest + requestWithURL:url + cachePolicy:policy + timeoutInterval:30.0 + ]]; +} + +- (void) loadURL:(NSURL *)url { + [self loadURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy]; +} + +- (id) init { + CGRect frame = {{0, 0}, {320, 480}}; + frame.size.height -= GSDefaultStatusBarHeight(); + + if ((self = [super initWithFrame:frame]) != nil) { + struct CGRect bounds([self bounds]); + + scroller_ = [[UIScroller alloc] initWithFrame:bounds]; + [self addSubview:scroller_]; + + [scroller_ setFixedBackgroundPattern:YES]; + [scroller_ setBackgroundColor:[UIColor blackColor]]; + + [scroller_ setScrollingEnabled:YES]; + [scroller_ setClipsSubviews:YES]; + [scroller_ setAllowsRubberBanding:YES]; + + [scroller_ setDelegate:self]; + [scroller_ setBounces:YES]; + [scroller_ setScrollHysteresis:8]; + [scroller_ setThumbDetectionEnabled:NO]; + [scroller_ setDirectionalScrolling:YES]; + [scroller_ setScrollDecelerationFactor:0.99]; /* 0.989324 */ + [scroller_ setEventMode:YES]; + [scroller_ setShowBackgroundShadow:NO]; /* YES */ + [scroller_ setAllowsRubberBanding:YES]; /* Vertical */ + [scroller_ setAdjustForContentSizeChange:YES]; /* NO */ + + CGRect rect([scroller_ bounds]); + //rect.size.height = 0; + + WebThreadLock(); + + document_ = [[UIWebDocumentView alloc] initWithFrame:rect]; + WebView *webview([document_ webView]); + + [document_ setBackgroundColor:[UIColor blackColor]]; + if ([document_ respondsToSelector:@selector(setDrawsBackground:)]) + [document_ setDrawsBackground:NO]; + [webview setDrawsBackground:NO]; + + [webview setPreferencesIdentifier:@"WebCycript"]; + + [document_ setTileSize:CGSizeMake(rect.size.width, 500)]; + + if ([document_ respondsToSelector:@selector(enableReachability)]) + [document_ enableReachability]; + + [document_ setAllowsMessaging:YES]; + + if ([document_ respondsToSelector:@selector(useSelectionAssistantWithMode:)]) + [document_ useSelectionAssistantWithMode:0]; + + [document_ setTilingEnabled:YES]; + [document_ setDrawsGrid:NO]; + [document_ setLogsTilingChanges:NO]; + [document_ setTileMinificationFilter:kCAFilterNearest]; + + if ([document_ respondsToSelector:@selector(setDataDetectorTypes:)]) + /* XXX: abstractify */ + [document_ setDataDetectorTypes:0x80000000]; + else + [document_ setDetectsPhoneNumbers:NO]; + + [document_ setAutoresizes:YES]; + + [document_ setMinimumScale:0.25f forDocumentTypes:0x10]; + [document_ setMaximumScale:5.00f forDocumentTypes:0x10]; + [document_ setInitialScale:UIWebViewScalesToFitScale forDocumentTypes:0x10]; + //[document_ setViewportSize:CGSizeMake(980, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10]; + + [document_ setViewportSize:CGSizeMake(320, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x2]; + + [document_ setMinimumScale:1.00f forDocumentTypes:0x8]; + [document_ setInitialScale:UIWebViewScalesToFitScale forDocumentTypes:0x8]; + [document_ setViewportSize:CGSizeMake(320, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x8]; + + [document_ _setDocumentType:0x4]; + + if ([document_ respondsToSelector:@selector(setZoomsFocusedFormControl:)]) + [document_ setZoomsFocusedFormControl:YES]; + [document_ setContentsPosition:7]; + [document_ setEnabledGestures:0xa]; + [document_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:UIGestureAttributeIsZoomRubberBandEnabled]; + [document_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:UIGestureAttributeUpdatesScroller]; + + [document_ setSmoothsFonts:YES]; + [document_ setAllowsImageSheet:YES]; + [webview _setUsesLoaderCache:YES]; + + [webview setGroupName:@"CydgetGroup"]; + + WebPreferences *preferences([webview preferences]); + + if ([webview respondsToSelector:@selector(_setLayoutInterval:)]) + [webview _setLayoutInterval:0]; + else + [preferences _setLayoutInterval:0]; + + [self setViewportWidth:0]; + + [document_ setDelegate:self]; + [document_ setGestureDelegate:self]; + [document_ setFormEditingDelegate:self]; + [document_ setInteractionDelegate:self]; + + [scroller_ addSubview:document_]; + + //NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + + indirect_ = [[WebCycriptDelegate alloc] initWithDelegate:self]; + + [webview setFrameLoadDelegate:indirect_]; + [webview setPolicyDelegate:indirect_]; + [webview setResourceLoadDelegate:indirect_]; + [webview setUIDelegate:indirect_]; + + /* XXX: do not turn this on under penalty of extreme pain */ + [webview setScriptDebugDelegate:nil]; + + WebThreadUnlock(); + + CGSize indsize([UIProgressIndicator defaultSizeForStyle:UIProgressIndicatorStyleMediumWhite]); + indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(281, 12, indsize.width, indsize.height)]; + [indicator_ setStyle:UIProgressIndicatorStyleMediumWhite]; + + [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight]; + [scroller_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight]; + + NSDictionary *configuration([$CydgetController currentConfiguration]); + NSString *homepage([configuration objectForKey:@"Homepage"]); + [self loadURL:[NSURL URLWithString:homepage]]; + } return self; +} + +- (void) webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame { + [self retain]; + + UIActionSheet *sheet = [[[UIActionSheet alloc] + initWithTitle:nil + buttons:[NSArray arrayWithObjects:@"OK", nil] + defaultButtonIndex:0 + delegate:self + context:@"alert" + ] autorelease]; + + [sheet setBodyText:message]; + [sheet popupAlertAnimated:YES]; +} + +- (BOOL) webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame { + [self retain]; + + UIActionSheet *sheet = [[[UIActionSheet alloc] + initWithTitle:nil + buttons:[NSArray arrayWithObjects:@"OK", @"CANCEL", nil] + defaultButtonIndex:0 + delegate:indirect_ + context:@"confirm" + ] autorelease]; + + [sheet setNumberOfRows:1]; + [sheet setBodyText:message]; + [sheet popupAlertAnimated:YES]; + + NSRunLoop *loop([NSRunLoop currentRunLoop]); + NSDate *future([NSDate distantFuture]); + + while (confirm_ == nil && [loop runMode:NSDefaultRunLoopMode beforeDate:future]); + + NSNumber *confirm([confirm_ autorelease]); + confirm_ = nil; + + [self autorelease]; + return [confirm boolValue]; +} + +/* XXX: WebThreadLock? */ +- (void) _fixScroller:(CGRect)bounds { + float extra; + if (!editing_) + extra = 0; + else { + UIFormAssistant *assistant([UIFormAssistant sharedFormAssistant]); + CGRect peripheral([assistant peripheralFrame]); + extra = peripheral.size.height; + } + + CGRect subrect([scroller_ frame]); + subrect.size.height -= extra; + [scroller_ setScrollerIndicatorSubrect:subrect]; + + NSSize visible(NSMakeSize(subrect.size.width, subrect.size.height)); + [document_ setValue:[NSValue valueWithSize:visible] forGestureAttribute:UIGestureAttributeVisibleSize]; + + CGSize size(size_); + size.height += extra; + [scroller_ setContentSize:size]; + + [scroller_ releaseRubberBandIfNecessary]; +} + +- (void) fixScroller { + CGRect bounds([document_ documentBounds]); + [self _fixScroller:bounds]; +} + +- (void) view:(UIView *)sender didSetFrame:(CGRect)frame { + size_ = frame.size; + [self _fixScroller:frame]; +} + +- (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old { + [self view:sender didSetFrame:frame]; +} + +- (void) webView:(WebView *)sender willBeginEditingFormElement:(id)element { + editing_ = true; +} + +- (void) webView:(WebView *)sender didBeginEditingFormElement:(id)element { + [self fixScroller]; +} + +- (void) webViewDidEndEditingFormElements:(WebView *)sender { + editing_ = false; + [self fixScroller]; +} + +- (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame { +} + +- (bool) isLoading { + return [loading_ count] != 0; +} + +- (void) reloadButtons { + if ([self isLoading]) + [indicator_ startAnimation]; + else + [indicator_ stopAnimation]; +} + +- (void) _finishLoading { + size_t count([loading_ count]); + /*if (count == 0) + [self autorelease];*/ + if (reloading_ || count != 0) + return; + [self reloadButtons]; +} + +- (BOOL) webView:(WebView *)sender shouldScrollToPoint:(struct CGPoint)point forFrame:(WebFrame *)frame { + return [document_ webView:sender shouldScrollToPoint:point forFrame:frame]; +} + +- (void) webView:(WebView *)sender didReceiveViewportArguments:(id)arguments forFrame:(WebFrame *)frame { + return [document_ webView:sender didReceiveViewportArguments:arguments forFrame:frame]; +} + +- (void) webView:(WebView *)sender needsScrollNotifications:(id)notifications forFrame:(WebFrame *)frame { + return [document_ webView:sender needsScrollNotifications:notifications forFrame:frame]; +} + +- (void) webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame { + return [document_ webView:sender didCommitLoadForFrame:frame]; +} + +- (void) webView:(WebView *)sender didReceiveDocTypeForFrame:(WebFrame *)frame { + return [document_ webView:sender didReceiveDocTypeForFrame:frame]; +} + +- (void) webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame { + [loading_ removeObject:[NSValue valueWithNonretainedObject:frame]]; + [self _finishLoading]; + return [document_ webView:sender didFinishLoadForFrame:frame]; +} + +- (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame { + /*if ([loading_ count] == 0) + [self retain];*/ + [loading_ addObject:[NSValue valueWithNonretainedObject:frame]]; + + if ([frame parentFrame] == nil) { + [document_ resignFirstResponder]; + + reloading_ = false; + + [scroller_ scrollPointVisibleAtTopLeft:CGPointZero]; + + if ([scroller_ respondsToSelector:@selector(setZoomScale:duration:)]) + [scroller_ setZoomScale:1 duration:0]; + else if ([scroller_ respondsToSelector:@selector(_setZoomScale:duration:)]) + [scroller_ _setZoomScale:1 duration:0]; + /*else if ([scroller_ respondsToSelector:@selector(setZoomScale:animated:)]) + [scroller_ setZoomScale:1 animated:NO];*/ + + CGRect rect([scroller_ bounds]); + //rect.size.height = 0; + [document_ setFrame:rect]; + } + + [self reloadButtons]; +} + +- (void) _didFailWithError:(NSError *)error forFrame:(WebFrame *)frame { + _trace(); + /*if ([frame parentFrame] == nil) + [self autorelease];*/ + + [loading_ removeObject:[NSValue valueWithNonretainedObject:frame]]; + [self _finishLoading]; + + if (reloading_) + return; + + if ([frame parentFrame] == nil) { + [self loadURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@?%@", + [[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"error" ofType:@"html"]] absoluteString], + [[error localizedDescription] stringByAddingPercentEscapes] + ]]]; + + error_ = true; + } +} + +- (void) webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { + [self _didFailWithError:error forFrame:frame]; +} + +- (void) webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { + [self _didFailWithError:error forFrame:frame]; +} + +- (void) webView:(WebView *)sender addMessageToConsole:(NSDictionary *)dictionary { + fprintf(stderr, "Console:%s\n", [[dictionary description] UTF8String]); +} + @end @interface WebCycriptLockScreenController : SBAwayViewPluginController { diff --git a/webcycript/control b/webcycript/control index 5a255d7..36014f7 100644 --- a/webcycript/control +++ b/webcycript/control @@ -3,7 +3,7 @@ Priority: optional Section: Development Maintainer: Jay Freeman (saurik) Architecture: iphoneos-arm -Version: 0.9.3067-1 +Version: 0.9.3073-1 Description: write LockCydgets using Cycript and HTML Name: Cydget WebCycript Depends: cydget, cycript diff --git a/webcycript/makefile b/webcycript/makefile index 09d4f33..fac7d59 100644 --- a/webcycript/makefile +++ b/webcycript/makefile @@ -1,5 +1,5 @@ name := WebCycript -flags := -lcycript -L/dat/src/cycript +flags := -lcycript -L/dat/src/cycript -framework QuartzCore -framework WebCore -framework CoreGraphics -framework GraphicsServices base := ../../tweaks include ../LockScreen.mk -- 2.45.2