📄 webpdfview.mm
字号:
// (1) the symptom is fairly minor, and (2) we suspect that non-Safari clients are probably using the entire // set of default items, rather than manually choosing from them. We can remove this code entirely when we // ship a version of Safari that includes the fix for radar 3796579. if (![self _anyPDFTagsFoundInMenu:menu] && [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"]) { [menu addItem:[NSMenuItem separatorItem]]; NSEnumerator *e = [items objectEnumerator]; NSMenuItem *menuItem; while ((menuItem = [e nextObject]) != nil) { // copy menuItem since a given menuItem can be in only one menu at a time, and we don't // want to mess with the menu returned from PDFKit. [menu addItem:[menuItem copy]]; } } return menu;}- (void)setNextKeyView:(NSView *)aView{ // This works together with becomeFirstResponder to splice PDFSubview into // the key loop similar to the way NSScrollView and NSClipView do this. NSView *documentView = [PDFSubview documentView]; if (documentView) { [documentView setNextKeyView:aView]; // We need to make the documentView be the next view in the keyview loop. // It would seem more sensible to do this in our init method, but it turns out // that [NSClipView setDocumentView] won't call this method if our next key view // is already set, so we wait until we're called before adding this connection. // We'll also clear it when we're called with nil, so this could go through the // same code path more than once successfully. [super setNextKeyView: aView ? documentView : nil]; } else [super setNextKeyView:aView];}- (void)viewDidMoveToWindow{ // FIXME 2573089: we can observe a notification for first responder changes // instead of the very frequent NSWindowDidUpdateNotification if/when 2573089 is addressed. NSWindow *newWindow = [self window]; if (!newWindow) return; [self _trackFirstResponder]; NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:self selector:@selector(_trackFirstResponder) name:NSWindowDidUpdateNotification object:newWindow]; [notificationCenter addObserver:self selector:@selector(_scaleOrDisplayModeOrPageChanged:) name:_webkit_PDFViewScaleChangedNotification object:PDFSubview]; [notificationCenter addObserver:self selector:@selector(_scaleOrDisplayModeOrPageChanged:) name:_webkit_PDFViewDisplayModeChangedNotification object:PDFSubview]; [notificationCenter addObserver:self selector:@selector(_scaleOrDisplayModeOrPageChanged:) name:_webkit_PDFViewPageChangedNotification object:PDFSubview]; [notificationCenter addObserver:self selector:@selector(_PDFDocumentViewMightHaveScrolled:) name:NSViewBoundsDidChangeNotification object:[self _clipViewForPDFDocumentView]];}- (void)viewWillMoveToWindow:(NSWindow *)window{ // FIXME 2573089: we can observe a notification for changes to the first responder // instead of the very frequent NSWindowDidUpdateNotification if/when 2573089 is addressed. NSWindow *oldWindow = [self window]; if (!oldWindow) return; NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter removeObserver:self name:NSWindowDidUpdateNotification object:oldWindow]; [notificationCenter removeObserver:self name:_webkit_PDFViewScaleChangedNotification object:PDFSubview]; [notificationCenter removeObserver:self name:_webkit_PDFViewDisplayModeChangedNotification object:PDFSubview]; [notificationCenter removeObserver:self name:_webkit_PDFViewPageChangedNotification object:PDFSubview]; [notificationCenter removeObserver:self name:NSViewBoundsDidChangeNotification object:[self _clipViewForPDFDocumentView]]; [trackedFirstResponder release]; trackedFirstResponder = nil;}#pragma mark NSUserInterfaceValidations PROTOCOL IMPLEMENTATION- (BOOL)validateUserInterfaceItemWithoutDelegate:(id <NSValidatedUserInterfaceItem>)item{ SEL action = [item action]; if (action == @selector(takeFindStringFromSelection:) || action == @selector(centerSelectionInVisibleArea:) || action == @selector(jumpToSelection:)) return [PDFSubview currentSelection] != nil; if (action == @selector(_openWithFinder:)) return [PDFSubview document] != nil; if (action == @selector(_lookUpInDictionaryFromMenu:)) return [self _canLookUpInDictionary]; return YES;}- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item{ // This can be called during teardown when _webView is nil. Return NO when this happens, because CallUIDelegateReturningBoolean // assumes the WebVIew is non-nil. if (![self _webView]) return NO; BOOL result = [self validateUserInterfaceItemWithoutDelegate:item]; return CallUIDelegateReturningBoolean(result, [self _webView], @selector(webView:validateUserInterfaceItem:defaultValidation:), item, result);}#pragma mark INTERFACE BUILDER ACTIONS FOR SAFARI// Surprisingly enough, this isn't defined in any superclass, though it is defined in assorted AppKit classes since// it's a standard menu item IBAction.- (IBAction)copy:(id)sender{ [PDFSubview copy:sender];}// This used to be a standard IBAction (for Use Selection For Find), but AppKit now uses performFindPanelAction:// with a menu item tag for this purpose.- (IBAction)takeFindStringFromSelection:(id)sender{ [NSPasteboard _web_setFindPasteboardString:[[PDFSubview currentSelection] string] withOwner:self];}#pragma mark WebFrameView UNDECLARED "DELEGATE METHODS"// This is tested in -[WebFrameView canPrintHeadersAndFooters], but isn't declared anywhere (yuck)- (BOOL)canPrintHeadersAndFooters{ return NO;}// This is tested in -[WebFrameView printOperationWithPrintInfo:], but isn't declared anywhere (yuck)- (NSPrintOperation *)printOperationWithPrintInfo:(NSPrintInfo *)printInfo{ return [[PDFSubview document] getPrintOperationForPrintInfo:printInfo autoRotate:YES];}#pragma mark WebDocumentView PROTOCOL IMPLEMENTATION- (void)setDataSource:(WebDataSource *)ds{ if (dataSource == ds) return; dataSource = [ds retain]; // FIXME: There must be some better place to put this. There is no comment in ChangeLog // explaining why it's in this method. [self setFrame:[[self superview] frame]];}- (void)dataSourceUpdated:(WebDataSource *)dataSource{}- (void)setNeedsLayout:(BOOL)flag{}- (void)layout{}- (void)viewWillMoveToHostWindow:(NSWindow *)hostWindow{}- (void)viewDidMoveToHostWindow{}#pragma mark WebDocumentElement PROTOCOL IMPLEMENTATION- (NSDictionary *)elementAtPoint:(NSPoint)point{ WebFrame *frame = [dataSource webFrame]; ASSERT(frame); return [NSDictionary dictionaryWithObjectsAndKeys: frame, WebElementFrameKey, [NSNumber numberWithBool:[self _pointIsInSelection:point]], WebElementIsSelectedKey, nil];}- (NSDictionary *)elementAtPoint:(NSPoint)point allowShadowContent:(BOOL)allow{ return [self elementAtPoint:point];}#pragma mark WebDocumentSearching PROTOCOL IMPLEMENTATION- (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag{ return [self searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:NO];}#pragma mark WebDocumentIncrementalSearching PROTOCOL IMPLEMENTATION- (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection{ PDFSelection *selection = [self _nextMatchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag fromSelection:[PDFSubview currentSelection] startInSelection:startInSelection]; if (!selection) return NO; [PDFSubview setCurrentSelection:selection]; [PDFSubview scrollSelectionToVisible:nil]; return YES;}#pragma mark WebMultipleTextMatches PROTOCOL IMPLEMENTATION- (void)setMarkedTextMatchesAreHighlighted:(BOOL)newValue{ // This method is part of the WebMultipleTextMatches algorithm, but this class doesn't support // highlighting text matches inline.#ifndef NDEBUG if (newValue) LOG_ERROR("[WebPDFView setMarkedTextMatchesAreHighlighted:] called with YES, which isn't supported");#endif}- (BOOL)markedTextMatchesAreHighlighted{ return NO;}- (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag limit:(NSUInteger)limit{ PDFSelection *previousMatch = nil; PDFSelection *nextMatch = nil; NSMutableArray *matches = [[NSMutableArray alloc] initWithCapacity:limit]; for (;;) { nextMatch = [self _nextMatchFor:string direction:YES caseSensitive:caseFlag wrap:NO fromSelection:previousMatch startInSelection:NO]; if (!nextMatch) break; [matches addObject:nextMatch]; previousMatch = nextMatch; if ([matches count] >= limit) break; } [self _setTextMatches:matches]; [matches release]; return [matches count];}- (void)unmarkAllTextMatches{ [self _setTextMatches:nil];}- (NSArray *)rectsForTextMatches{ NSMutableArray *result = [NSMutableArray arrayWithCapacity:[textMatches count]]; NSSet *visiblePages = [self _visiblePDFPages]; NSEnumerator *matchEnumerator = [textMatches objectEnumerator]; PDFSelection *match; while ((match = [matchEnumerator nextObject]) != nil) { NSEnumerator *pages = [[match pages] objectEnumerator]; PDFPage *page; while ((page = [pages nextObject]) != nil) { // Skip pages that aren't visible (needed for non-continuous modes, see 5362989) if (![visiblePages containsObject:page]) continue; NSRect selectionOnPageInPDFViewCoordinates = [PDFSubview convertRect:[match boundsForPage:page] fromPage:page]; [result addObject:[NSValue valueWithRect:selectionOnPageInPDFViewCoordinates]]; } } return result;}#pragma mark WebDocumentText PROTOCOL IMPLEMENTATION- (BOOL)supportsTextEncoding{ return NO;}- (NSString *)string{ return [[PDFSubview document] string];}- (NSAttributedString *)attributedString{ // changing the selection is a hack, but the only way to get an attr string is via PDFSelection // must copy this selection object because we change the selection which seems to release it PDFSelection *savedSelection = [[PDFSubview currentSelection] copy]; [PDFSubview selectAll:nil]; NSAttributedString *result = [[PDFSubview currentSelection] attributedString]; if (savedSelection) { [PDFSubview setCurrentSelection:savedSelection]; [savedSelection release]; } else { // FIXME: behavior of setCurrentSelection:nil is not documented - check 4182934 for progress // Otherwise, we could collapse this code with the case above. [PDFSubview clearSelection]; } result = [self _scaledAttributedString:result]; return result;}- (NSString *)selectedString{ return [[PDFSubview currentSelection] string];}- (NSAttributedString *)selectedAttributedString{ return [self _scaledAttributedString:[[PDFSubview currentSelection] attributedString]];}- (void)selectAll{ [PDFSubview selectAll:nil];}- (void)deselectAll{ [PDFSubview clearSelection];}#pragma mark WebDocumentViewState PROTOCOL IMPLEMENTATION// Even though to WebKit we are the "docView", in reality a PDFView contains its own scrollview and docView.// And it even turns out there is another PDFKit view between the docView and its enclosing ScrollView, so// we have to be sure to do our calculations based on that view, immediately inside the ClipView. We try// to make as few assumptions about the PDFKit view hierarchy as possible.- (NSPoint)scrollPoint{ NSView *realDocView = [PDFSubview documentView]; NSClipView *clipView = [[realDocView enclosingScrollView] contentView]; return [clipView bounds].origin;}- (void)setScrollPoint:(NSPoint)p{ WebFrame *frame = [dataSource webFrame];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -