📄 webframeview.mm
字号:
[self addSubview:scrollView]; // Don't call our overridden version of setNextKeyView here; we need to make the standard NSView // link between us and our subview so that previousKeyView and previousValidKeyView work as expected. // This works together with our becomeFirstResponder and setNextKeyView overrides. [super setNextKeyView:scrollView]; ++WebFrameViewCount; return self;}- (void)dealloc { --WebFrameViewCount; [_private release]; _private = nil; [super dealloc];}- (void)finalize { --WebFrameViewCount; [super finalize];}- (WebFrame *)webFrame{ return _private->webFrame;}- (void)setAllowsScrolling:(BOOL)flag{ WebCore::Frame *frame = core([self webFrame]); if (WebCore::FrameView *view = frame? frame->view() : 0) view->setCanHaveScrollbars(flag);}- (BOOL)allowsScrolling{ WebCore::Frame *frame = core([self webFrame]); if (WebCore::FrameView *view = frame? frame->view() : 0) return view->canHaveScrollbars(); return YES;}- (NSView <WebDocumentView> *)documentView{ return [[self _scrollView] documentView];}- (BOOL)acceptsFirstResponder{ // We always accept first responder; this matches OS X 10.2 WebKit // behavior (see 3469791). return YES;}- (BOOL)becomeFirstResponder{ // This works together with setNextKeyView to splice the WebFrameView into // the key loop similar to the way NSScrollView does this. Note that // WebView has similar code. NSWindow *window = [self window]; if ([window keyViewSelectionDirection] == NSSelectingPrevious) { NSView *previousValidKeyView = [self previousValidKeyView]; // If we couldn't find a previous valid key view, ask the WebView. This handles frameset // cases (one is mentioned in Radar bug 3748628). Note that previousValidKeyView should // never be self but can be due to AppKit oddness (mentioned in Radar bug 3748628). if (previousValidKeyView == nil || previousValidKeyView == self) previousValidKeyView = [[[self webFrame] webView] previousValidKeyView]; [window makeFirstResponder:previousValidKeyView]; } else { // If the scroll view won't accept first-responderness now, then just become // the first responder ourself like a normal view. This lets us be the first // responder in cases where no page has yet been loaded. if ([[self _scrollView] acceptsFirstResponder]) [window makeFirstResponder:[self _scrollView]]; } return YES;}- (void)setNextKeyView:(NSView *)aView{ // This works together with becomeFirstResponder to splice the WebFrameView into // the key loop similar to the way NSScrollView does this. Note that // WebView has very similar code. if ([self _scrollView] != nil) { [[self _scrollView] setNextKeyView:aView]; } else { [super setNextKeyView:aView]; }}- (BOOL)isOpaque{ return [[self _webView] drawsBackground];}- (void)drawRect:(NSRect)rect{ if ([self documentView] == nil) { // Need to paint ourselves if there's no documentView to do it instead. if ([[self _webView] drawsBackground]) { [[[self _webView] backgroundColor] set]; NSRectFill(rect); } } else {#ifndef NDEBUG if ([[self _scrollView] drawsBackground]) { [[NSColor cyanColor] set]; NSRectFill(rect); }#endif }}- (NSRect)visibleRect{ // This method can be called beneath -[NSView dealloc] after we have cleared _private. if (!_private) return [super visibleRect]; // FIXME: <rdar://problem/6213380> This method does not work correctly with transforms, for two reasons: // 1) [super visibleRect] does not account for the transform, since it is not represented // in the NSView hierarchy. // 2) -_getVisibleRect: does not correct for transforms. NSRect rendererVisibleRect; if (![[self webFrame] _getVisibleRect:&rendererVisibleRect]) return [super visibleRect]; if (NSIsEmptyRect(rendererVisibleRect)) return NSZeroRect; NSRect viewVisibleRect = [super visibleRect]; if (NSIsEmptyRect(viewVisibleRect)) return NSZeroRect; NSRect frame = [self frame]; // rendererVisibleRect is in the parent's coordinate space, and frame is in the superview's coordinate space. // The return value from this method needs to be in this view's coordinate space. We get that right by subtracting // the origins (and correcting for flipping), but when we support transforms, we will need to do better than this. rendererVisibleRect.origin.x -= frame.origin.x; rendererVisibleRect.origin.y = NSMaxY(frame) - NSMaxY(rendererVisibleRect); return NSIntersectionRect(rendererVisibleRect, viewVisibleRect);}- (void)setFrameSize:(NSSize)size{ // See WebFrameLoaderClient::provisionalLoadStarted. if (!NSEqualSizes(size, [self frame].size) && [[[self webFrame] webView] drawsBackground]) [[self _scrollView] setDrawsBackground:YES]; [super setFrameSize:size];}- (void)viewDidMoveToWindow{ // See WebFrameLoaderClient::provisionalLoadStarted. // Need to check _private for nil because this can be called inside -[WebView initWithCoder:]. if (_private && [[[self webFrame] webView] drawsBackground]) [[self _scrollView] setDrawsBackground:YES]; [super viewDidMoveToWindow];}- (BOOL)_scrollOverflowInDirection:(ScrollDirection)direction granularity:(ScrollGranularity)granularity{ // scrolling overflows is only applicable if we're dealing with an WebHTMLView if (![[self documentView] isKindOfClass:[WebHTMLView class]]) return NO; Frame* frame = core([self webFrame]); if (!frame) return NO; return frame->eventHandler()->scrollOverflow(direction, granularity);}- (void)scrollToBeginningOfDocument:(id)sender{ if (![self _scrollOverflowInDirection:ScrollUp granularity:ScrollByDocument]) { if (![self _hasScrollBars]) { [[self _largestChildWithScrollBars] scrollToBeginningOfDocument:sender]; return; } [[self _contentView] scrollPoint:[[[self _scrollView] documentView] frame].origin]; }}- (void)scrollToEndOfDocument:(id)sender{ if (![self _scrollOverflowInDirection:ScrollDown granularity:ScrollByDocument]) { if (![self _hasScrollBars]) { [[self _largestChildWithScrollBars] scrollToEndOfDocument:sender]; return; } NSRect frame = [[[self _scrollView] documentView] frame]; [[self _contentView] scrollPoint:NSMakePoint(frame.origin.x, NSMaxY(frame))]; }}- (void)_goBack{ [[self _webView] goBack];}- (void)_goForward{ [[self _webView] goForward];}- (BOOL)_scrollVerticallyBy:(float)delta{ // This method uses the secret method _scrollTo on NSClipView. // It does that because it needs to know definitively whether scrolling was // done or not to help implement the "scroll parent if we are at the limit" feature. // In the presence of smooth scrolling, there's no easy way to tell if the method // did any scrolling or not with the public API. NSPoint point = [[self _contentView] bounds].origin; point.y += delta; return [[self _contentView] _scrollTo:&point animate:YES];}- (BOOL)_scrollHorizontallyBy:(float)delta{ NSPoint point = [[self _contentView] bounds].origin; point.x += delta; return [[self _contentView] _scrollTo:&point animate:YES];}- (float)_horizontalKeyboardScrollDistance{ // Arrow keys scroll the same distance that clicking the scroll arrow does. return [[self _scrollView] horizontalLineScroll];}- (float)_horizontalPageScrollDistance{ float overlap = [self _horizontalKeyboardScrollDistance]; float width = [[self _contentView] bounds].size.width; return (width < overlap) ? width / 2 : width - overlap;}- (BOOL)_pageVertically:(BOOL)up{ if ([self _scrollOverflowInDirection:up ? ScrollUp : ScrollDown granularity:ScrollByPage]) return YES; if (![self _hasScrollBars]) return [[self _largestChildWithScrollBars] _pageVertically:up]; float delta = [self _verticalPageScrollDistance]; return [self _scrollVerticallyBy:up ? -delta : delta];}- (BOOL)_pageHorizontally:(BOOL)left{ if ([self _scrollOverflowInDirection:left ? ScrollLeft : ScrollRight granularity:ScrollByPage]) return YES; if (![self _hasScrollBars]) return [[self _largestChildWithScrollBars] _pageHorizontally:left]; float delta = [self _horizontalPageScrollDistance]; return [self _scrollHorizontallyBy:left ? -delta : delta];}- (BOOL)_scrollLineVertically:(BOOL)up{ if ([self _scrollOverflowInDirection:up ? ScrollUp : ScrollDown granularity:ScrollByLine]) return YES; if (![self _hasScrollBars]) return [[self _largestChildWithScrollBars] _scrollLineVertically:up]; float delta = [self _verticalKeyboardScrollDistance]; return [self _scrollVerticallyBy:up ? -delta : delta];}- (BOOL)_scrollLineHorizontally:(BOOL)left{ if ([self _scrollOverflowInDirection:left ? ScrollLeft : ScrollRight granularity:ScrollByLine]) return YES; if (![self _hasScrollBars]) return [[self _largestChildWithScrollBars] _scrollLineHorizontally:left]; float delta = [self _horizontalKeyboardScrollDistance]; return [self _scrollHorizontallyBy:left ? -delta : delta];}- (void)scrollPageUp:(id)sender{ if (![self _pageVertically:YES]) { // If we were already at the top, tell the next responder to scroll if it can. [[self nextResponder] tryToPerform:@selector(scrollPageUp:) with:sender]; }}- (void)scrollPageDown:(id)sender{ if (![self _pageVertically:NO]) { // If we were already at the bottom, tell the next responder to scroll if it can. [[self nextResponder] tryToPerform:@selector(scrollPageDown:) with:sender]; }}- (void)scrollLineUp:(id)sender{ [self _scrollLineVertically:YES];}- (void)scrollLineDown:(id)sender{ [self _scrollLineVertically:NO];}- (BOOL)_firstResponderIsFormControl{ NSResponder *firstResponder = [[self window] firstResponder]; // WebHTMLView is an NSControl subclass these days, but it's not a form control
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -