📄 webframe.mm
字号:
SelectionController selection; selection.setSelection(_private->coreFrame->selection()->selection()); selection.modify(alteration, direction, granularity); return [DOMRange _wrapRange:selection.toNormalizedRange().get()];}- (TextGranularity)_selectionGranularity{ return _private->coreFrame->selectionGranularity();}- (NSRange)_convertToNSRange:(Range *)range{ if (!range || !range->startContainer()) return NSMakeRange(NSNotFound, 0); Element* selectionRoot = _private->coreFrame->selection()->rootEditableElement(); Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement(); // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view // that is not inside the current editable region. These checks ensure we don't produce // potentially invalid data when responding to such requests. if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope)) return NSMakeRange(NSNotFound, 0); if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope)) return NSMakeRange(NSNotFound, 0); RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset()); ASSERT(testRange->startContainer() == scope); int startPosition = TextIterator::rangeLength(testRange.get()); ExceptionCode ec; testRange->setEnd(range->endContainer(), range->endOffset(), ec); ASSERT(testRange->startContainer() == scope); int endPosition = TextIterator::rangeLength(testRange.get()); return NSMakeRange(startPosition, endPosition - startPosition);}- (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange{ if (nsrange.location > INT_MAX) return 0; if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX) nsrange.length = INT_MAX - nsrange.location; // our critical assumption is that we are only called by input methods that // concentrate on a given area containing the selection // We have to do this because of text fields and textareas. The DOM for those is not // directly in the document DOM, so serialization is problematic. Our solution is // to use the root editable element of the selection start as the positional base. // That fits with AppKit's idea of an input context. Element* selectionRoot = _private->coreFrame->selection()->rootEditableElement(); Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement(); return TextIterator::rangeFromLocationAndLength(scope, nsrange.location, nsrange.length);}- (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange{ // This method exists to maintain compatibility with Leopard's Dictionary.app. <rdar://problem/6002160> return [self _convertNSRangeToDOMRange:nsrange];}- (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange{ return [DOMRange _wrapRange:[self _convertToDOMRange:nsrange].get()];}- (NSRange)convertDOMRangeToNSRange:(DOMRange *)range{ // This method exists to maintain compatibility with Leopard's Dictionary.app. <rdar://problem/6002160> return [self _convertDOMRangeToNSRange:range];}- (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range{ return [self _convertToNSRange:[range _range]];}- (DOMRange *)_markDOMRange{ return [DOMRange _wrapRange:_private->coreFrame->mark().toNormalizedRange().get()];}// Given proposedRange, returns an extended range that includes adjacent whitespace that should// be deleted along with the proposed range in order to preserve proper spacing and punctuation of// the text surrounding the deletion.- (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange{ Node *startContainer = [[proposedRange startContainer] _node]; Node *endContainer = [[proposedRange endContainer] _node]; if (startContainer == nil || endContainer == nil) return nil; ASSERT(startContainer->document() == endContainer->document()); _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets(); Position start(startContainer, [proposedRange startOffset]); Position end(endContainer, [proposedRange endOffset]); Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true); if (newStart.isNull()) newStart = start; Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true); if (newEnd.isNull()) newEnd = end; newStart = rangeCompliantEquivalent(newStart); newEnd = rangeCompliantEquivalent(newEnd); RefPtr<Range> range = _private->coreFrame->document()->createRange(); int exception = 0; range->setStart(newStart.node(), newStart.offset(), exception); range->setEnd(newStart.node(), newStart.offset(), exception); return [DOMRange _wrapRange:range.get()];}// Determines whether whitespace needs to be added around aString to preserve proper spacing and// punctuation when it’s inserted into the receiver’s text over charRange. Returns by reference// in beforeString and afterString any whitespace that should be added, unless either or both are// nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.- (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString{ // give back nil pointers in case of early returns if (beforeString) *beforeString = nil; if (afterString) *afterString = nil; // inspect destination Node *startContainer = [[rangeToReplace startContainer] _node]; Node *endContainer = [[rangeToReplace endContainer] _node]; Position startPos(startContainer, [rangeToReplace startOffset]); Position endPos(endContainer, [rangeToReplace endOffset]); VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY); VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY); // this check also ensures startContainer, startPos, endContainer, and endPos are non-null if (startVisiblePos.isNull() || endVisiblePos.isNull()) return; bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos); if (addLeadingSpace) if (UChar previousChar = startVisiblePos.previous().characterAfter()) addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true); bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos); if (addTrailingSpace) if (UChar thisChar = endVisiblePos.characterAfter()) addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false); // inspect source bool hasWhitespaceAtStart = false; bool hasWhitespaceAtEnd = false; unsigned pasteLength = [pasteString length]; if (pasteLength > 0) { NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) { hasWhitespaceAtStart = YES; } if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) { hasWhitespaceAtEnd = YES; } } // issue the verdict if (beforeString && addLeadingSpace && !hasWhitespaceAtStart) *beforeString = @" "; if (afterString && addTrailingSpace && !hasWhitespaceAtEnd) *afterString = @" ";}- (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString { if (!_private->coreFrame || !_private->coreFrame->document()) return 0; return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString).get()];}- (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes{ if (!_private->coreFrame || !_private->coreFrame->document()) return 0; NSEnumerator *nodeEnum = [nodes objectEnumerator]; Vector<Node*> nodesVector; DOMNode *node; while ((node = [nodeEnum nextObject])) nodesVector.append([node _node]); return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get()];}- (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle{ DOMDocumentFragment *fragment = [DOMDocumentFragment _wrapDocumentFragment:_private->coreFrame->document()->createDocumentFragment().get()]; [fragment appendChild:node]; [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];}- (void)_insertParagraphSeparatorInQuotedContent{ if (_private->coreFrame->selection()->isNone()) return; TypingCommand::insertParagraphSeparatorInQuotedContent(_private->coreFrame->document()); _private->coreFrame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);}- (VisiblePosition)_visiblePositionForPoint:(NSPoint)point{ // FIXME: Someone with access to Apple's sources could remove this needless wrapper call. return _private->coreFrame->visiblePositionForPoint(IntPoint(point));}- (DOMRange *)_characterRangeAtPoint:(NSPoint)point{ VisiblePosition position = [self _visiblePositionForPoint:point]; if (position.isNull()) return nil; VisiblePosition previous = position.previous(); if (previous.isNotNull()) { DOMRange *previousCharacterRange = [DOMRange _wrapRange:makeRange(previous, position).get()]; NSRect rect = [self _firstRectForDOMRange:previousCharacterRange]; if (NSPointInRect(point, rect)) return previousCharacterRange; } VisiblePosition next = position.next(); if (next.isNotNull()) { DOMRange *nextCharacterRange = [DOMRange _wrapRange:makeRange(position, next).get()]; NSRect rect = [self _firstRectForDOMRange:nextCharacterRange]; if (NSPointInRect(point, rect)) return nextCharacterRange; } return nil;}- (DOMCSSStyleDeclaration *)_typingStyle{ if (!_private->coreFrame || !_private->coreFrame->typingStyle()) return nil; return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:_private->coreFrame->typingStyle()->copy().get()];}- (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction{ if (!_private->coreFrame) return; _private->coreFrame->computeAndSetTypingStyle([style _CSSStyleDeclaration], undoAction);}- (void)_dragSourceMovedTo:(NSPoint)windowLoc{ if (!_private->coreFrame) return; FrameView* view = _private->coreFrame->view(); if (!view) return; // FIXME: These are fake modifier keys here, but they should be real ones instead. PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]), LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime()); _private->coreFrame->eventHandler()->dragSourceMovedTo(event);}- (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation{ if (!_private->coreFrame) return; FrameView* view = _private->coreFrame->view(); if (!view) return; // FIXME: These are fake modifier keys here, but they should be real ones instead. PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]), LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime()); _private->coreFrame->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);}- (BOOL)_canProvideDocumentSource{ Frame* frame = _private->coreFrame; String mimeType = frame->loader()->responseMIMEType(); PluginData* pluginData = frame->page() ? frame->page()->pluginData() : 0; if (WebCore::DOMImplementation::isTextMIMEType(mimeType) || Image::supportsType(mimeType) || (pluginData && pluginData->supportsMimeType(mimeType))) return NO; return YES;}- (BOOL)_canSaveAsWebArchive{ // Currently, all documents that we can view source for // (HTML and XML documents) can also be saved as web archives return [self _canProvideDocumentSource];}- (void)_receivedData:(NSData *)data textEncodingName:(NSString *)textEncodingName{ // Set the encoding. This only needs to be done once, but it's harmless to do it again later. String encoding = _private->coreFrame->loader()->documentLoader()->overrideEncoding(); bool userChosen = !encoding.isNull(); if (encoding.isNull()) encoding = textEncodingName; _private->coreFrame->loader()->setEncoding(encoding, userChosen); [self _addData:data];}@end@implementation WebFrame (WebPrivate)// FIXME: This exists only as a convenience for Safari, consider moving there.- (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor{ Frame* coreFrame = _private->coreFrame; return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor));}- (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers{ _private->shouldCreateRenderers = shouldCreateRenderers;}- (NSColor *)_bodyBackgroundColor{ Document* document = _private->coreFrame->document(); if (!document) return nil; HTMLElement* body = document->body(); if (!body) return nil; RenderObject* bodyRenderer = body->renderer(); if (!bodyRenderer) return nil; Color color = bodyRenderer->style()->backgroundColor(); if (!color.isValid()) return nil; return nsColor(color);}- (BOOL)_isFrameSet{ Document* document = _private->coreFrame->document(); return document && document->isFrameSet();}- (BOOL)_firstLayoutDone{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -