📄 webpdfview.mm
字号:
//FIXME: We only restore scroll state in the non-frames case because otherwise we get a crash due to // PDFKit calling display from within its drawRect:. See bugzilla 4164. if (![frame parentFrame]) { NSView *realDocView = [PDFSubview documentView]; [[[realDocView enclosingScrollView] documentView] scrollPoint:p]; }}- (id)viewState{ NSMutableArray *state = [NSMutableArray arrayWithCapacity:4]; PDFDisplayMode mode = [PDFSubview displayMode]; [state addObject:[NSNumber numberWithInt:mode]]; if (mode == kPDFDisplaySinglePage || mode == kPDFDisplayTwoUp) { unsigned int pageIndex = [[PDFSubview document] indexForPage:[PDFSubview currentPage]]; [state addObject:[NSNumber numberWithUnsignedInt:pageIndex]]; } // else in continuous modes, scroll position gets us to the right page BOOL autoScaleFlag = [PDFSubview autoScales]; [state addObject:[NSNumber numberWithBool:autoScaleFlag]]; if (!autoScaleFlag) [state addObject:[NSNumber numberWithFloat:[PDFSubview scaleFactor]]]; return state;}- (void)setViewState:(id)statePList{ ASSERT([statePList isKindOfClass:[NSArray class]]); NSArray *state = statePList; int i = 0; PDFDisplayMode mode = [[state objectAtIndex:i++] intValue]; [PDFSubview setDisplayMode:mode]; if (mode == kPDFDisplaySinglePage || mode == kPDFDisplayTwoUp) { unsigned int pageIndex = [[state objectAtIndex:i++] unsignedIntValue]; [PDFSubview goToPage:[[PDFSubview document] pageAtIndex:pageIndex]]; } // else in continuous modes, scroll position gets us to the right page BOOL autoScaleFlag = [[state objectAtIndex:i++] boolValue]; [PDFSubview setAutoScales:autoScaleFlag]; if (!autoScaleFlag) [PDFSubview setScaleFactor:[[state objectAtIndex:i++] floatValue]];}#pragma mark _WebDocumentTextSizing PROTOCOL IMPLEMENTATION- (IBAction)_zoomOut:(id)sender{ [PDFSubviewProxy zoomOut:sender];}- (IBAction)_zoomIn:(id)sender{ [PDFSubviewProxy zoomIn:sender];}- (IBAction)_resetZoom:(id)sender{ [PDFSubviewProxy setScaleFactor:1.0f];}- (BOOL)_canZoomOut{ return [PDFSubview canZoomOut];}- (BOOL)_canZoomIn{ return [PDFSubview canZoomIn];}- (BOOL)_canResetZoom{ return [PDFSubview scaleFactor] != 1.0;}#pragma mark WebDocumentSelection PROTOCOL IMPLEMENTATION- (NSRect)selectionRect{ NSRect result = NSZeroRect; PDFSelection *selection = [PDFSubview currentSelection]; NSEnumerator *pages = [[selection pages] objectEnumerator]; PDFPage *page; while ((page = [pages nextObject]) != nil) { NSRect selectionOnPageInPDFViewCoordinates = [PDFSubview convertRect:[selection boundsForPage:page] fromPage:page]; if (NSIsEmptyRect(result)) result = selectionOnPageInPDFViewCoordinates; else result = NSUnionRect(result, selectionOnPageInPDFViewCoordinates); } // Convert result to be in documentView (selectionView) coordinates result = [PDFSubview convertRect:result toView:[PDFSubview documentView]]; return result;}- (NSArray *)selectionTextRects{ // FIXME: We'd need new PDFKit API/SPI to get multiple text rects for selections that intersect more than one line return [NSArray arrayWithObject:[NSValue valueWithRect:[self selectionRect]]];}- (NSView *)selectionView{ return [PDFSubview documentView];}- (NSImage *)selectionImageForcingBlackText:(BOOL)forceBlackText{ // Convert the selection to an attributed string, and draw that. // FIXME 4621154: this doesn't handle italics (and maybe other styles) // FIXME 4604366: this doesn't handle text at non-actual size NSMutableAttributedString *attributedString = [[self selectedAttributedString] mutableCopy]; NSRange wholeStringRange = NSMakeRange(0, [attributedString length]); // Modify the styles in the attributed string to draw black text, no background, and no underline. We draw // no underline because it would look ugly. [attributedString beginEditing]; [attributedString removeAttribute:NSBackgroundColorAttributeName range:wholeStringRange]; [attributedString removeAttribute:NSUnderlineStyleAttributeName range:wholeStringRange]; if (forceBlackText) [attributedString addAttribute:NSForegroundColorAttributeName value:[NSColor colorWithDeviceWhite:0.0f alpha:1.0f] range:wholeStringRange]; [attributedString endEditing]; NSImage* selectionImage = [[[NSImage alloc] initWithSize:[self selectionRect].size] autorelease]; [selectionImage lockFocus]; [attributedString drawAtPoint:NSZeroPoint]; [selectionImage unlockFocus]; [attributedString release]; return selectionImage;}- (NSRect)selectionImageRect{ // FIXME: deal with clipping? return [self selectionRect];}- (NSArray *)pasteboardTypesForSelection{ return [NSArray arrayWithObjects:NSRTFDPboardType, NSRTFPboardType, NSStringPboardType, nil];}- (void)writeSelectionWithPasteboardTypes:(NSArray *)types toPasteboard:(NSPasteboard *)pasteboard{ NSAttributedString *attributedString = [self selectedAttributedString]; if ([types containsObject:NSRTFDPboardType]) { NSData *RTFDData = [attributedString RTFDFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil]; [pasteboard setData:RTFDData forType:NSRTFDPboardType]; } if ([types containsObject:NSRTFPboardType]) { if ([attributedString containsAttachments]) attributedString = [attributedString _web_attributedStringByStrippingAttachmentCharacters]; NSData *RTFData = [attributedString RTFFromRange:NSMakeRange(0, [attributedString length]) documentAttributes:nil]; [pasteboard setData:RTFData forType:NSRTFPboardType]; } if ([types containsObject:NSStringPboardType]) [pasteboard setString:[self selectedString] forType:NSStringPboardType];}#pragma mark PDFView DELEGATE METHODS- (void)PDFViewWillClickOnLink:(PDFView *)sender withURL:(NSURL *)URL{ if (!URL) return; NSWindow *window = [sender window]; NSEvent *nsEvent = [window currentEvent]; const int noButton = -1; int button = noButton; RefPtr<Event> event; switch ([nsEvent type]) { case NSLeftMouseUp: button = 0; break; case NSRightMouseUp: button = 1; break; case NSOtherMouseUp: button = [nsEvent buttonNumber]; break; case NSKeyDown: { PlatformKeyboardEvent pe(nsEvent); pe.disambiguateKeyDownEvent(PlatformKeyboardEvent::RawKeyDown); event = KeyboardEvent::create(eventNames().keydownEvent, true, true, 0, pe.keyIdentifier(), pe.windowsVirtualKeyCode(), pe.ctrlKey(), pe.altKey(), pe.shiftKey(), pe.metaKey(), false); } default: break; } if (button != noButton) event = MouseEvent::create(eventNames().clickEvent, true, true, 0, [nsEvent clickCount], 0, 0, 0, 0, [nsEvent modifierFlags] & NSControlKeyMask, [nsEvent modifierFlags] & NSAlternateKeyMask, [nsEvent modifierFlags] & NSShiftKeyMask, [nsEvent modifierFlags] & NSCommandKeyMask, button, 0, 0, true); // Call to the frame loader because this is where our security checks are made. core([dataSource webFrame])->loader()->loadFrameRequestWithFormAndValues(ResourceRequest(URL), false, false, event.get(), 0, HashMap<String, String>());}- (void)PDFViewOpenPDFInNativeApplication:(PDFView *)sender{ // Delegate method sent when the user requests opening the PDF file in the system's default app [self _openWithFinder:sender];}- (void)PDFViewPerformPrint:(PDFView *)sender{ CallUIDelegate([self _webView], @selector(webView:printFrameView:), [[dataSource webFrame] frameView]);}- (void)PDFViewSavePDFToDownloadFolder:(PDFView *)sender{ // We don't want to write the file until we have a document to write (see 5267607). if (![PDFSubview document]) { NSBeep(); return; } // Delegate method sent when the user requests downloading the PDF file to disk. We pass NO for // showingPanel: so that the PDF file is saved to the standard location without user intervention. CallUIDelegate([self _webView], @selector(webView:saveFrameView:showingPanel:), [[dataSource webFrame] frameView], NO);}@end@implementation WebPDFView (FileInternal)+ (Class)_PDFPreviewViewClass{ static Class PDFPreviewViewClass = nil; static BOOL checkedForPDFPreviewViewClass = NO; if (!checkedForPDFPreviewViewClass) { checkedForPDFPreviewViewClass = YES; PDFPreviewViewClass = [[WebPDFView PDFKitBundle] classNamed:@"PDFPreviewView"]; } // This class might not be available; callers need to deal with a nil return here. return PDFPreviewViewClass;}+ (Class)_PDFViewClass{ static Class PDFViewClass = nil; if (PDFViewClass == nil) { PDFViewClass = [[WebPDFView PDFKitBundle] classNamed:@"PDFView"]; if (!PDFViewClass) LOG_ERROR("Couldn't find PDFView class in PDFKit.framework"); } return PDFViewClass;}- (BOOL)_anyPDFTagsFoundInMenu:(NSMenu *)menu{ NSEnumerator *e = [[menu itemArray] objectEnumerator]; NSMenuItem *item; while ((item = [e nextObject]) != nil) { switch ([item tag]) { case WebMenuItemTagOpenWithDefaultApplication: case WebMenuItemPDFActualSize: case WebMenuItemPDFZoomIn: case WebMenuItemPDFZoomOut: case WebMenuItemPDFAutoSize: case WebMenuItemPDFSinglePage: case WebMenuItemPDFSinglePageScrolling: case WebMenuItemPDFFacingPages: case WebMenuItemPDFFacingPagesScrolling: case WebMenuItemPDFContinuous: case WebMenuItemPDFNextPage: case WebMenuItemPDFPreviousPage: return YES; } } return NO;}- (void)_applyPDFDefaults{ // Set up default viewing params WebPreferences *prefs = [[dataSource _webView] preferences]; float scaleFactor = [prefs PDFScaleFactor]; if (scaleFactor == 0) [PDFSubview setAutoScales:YES]; else { [PDFSubview setAutoScales:NO]; [PDFSubview setScaleFactor:scaleFactor]; } [PDFSubview setDisplayMode:[prefs PDFDisplayMode]];}- (BOOL)_canLookUpInDictionary{ return [PDFSubview respondsToSelector:@selector(_searchInDictionary:)];}- (NSClipView *)_clipViewForPDFDocumentView{ NSClipView *clipView = (NSClipView *)[[PDFSubview documentView] _web_superviewOfClass:[NSClipView class]]; ASSERT(clipView); return clipView;}- (NSEvent *)_fakeKeyEventWithFunctionKey:(unichar)functionKey{ // FIXME 4400480: when PDFView implements the standard scrolling selectors that this // method is used to mimic, we can eliminate this method and call them directly. NSString *keyAsString = [NSString stringWithCharacters:&functionKey length:1]; return [NSEvent keyEventWithType:NSKeyDown location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:0 context:nil characters:keyAsString charactersIgnoringModifiers:keyAsString isARepeat:NO keyCode:0];}- (void)_lookUpInDictionaryFromMenu:(id)sender{ // This method is used by WebKit's context menu item. Here we map to the method that // PDFView uses. Since the PDFView method isn't API, and isn't available on all versions // of PDFKit, we use performSelector after a respondsToSelector check, rather than calling it directly. if ([self _canLookUpInDictionary]) [PDFSubview performSelector:@selector(_searchInDictionary:) withObject:sender];}- (NSMutableArray *)_menuItemsFromPDFKitForEvent:(NSEvent *)theEvent{ NSMutableArray *copiedItems = [NSMutableArray array]; NSDictionary *actionsToTags = [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithInt:WebMenuItemPDFActualSize], NSStringFromSelector(@selector(_setActualSize:)), [NSNumber numberWithInt:WebMenuItemPDFZoomIn], NSStringFromSelector(@selector(zoomIn:)), [NSNumber numberWithInt:WebMenuItemPDFZoomOut], NSStringFromSelector(@selector(zoomOut:)), [NSNumber numberWithInt:WebMenuItemPDFAutoSize], NSStringFromSelector(@selector(_setAutoSize:)), [NSNumber numberWithInt:WebMenuItemPDFSinglePage], NSStringFromSelector(@selector(_setSinglePage:)), [NSNumber numberWithInt:WebMenuItemPDFSinglePageScrolling], NSStringFromSelector(@selector(_setSinglePageScrolling:)), [NSNumber numberWithInt:WebMenuItemPDFFacingPages], NSStringFromSelector(@selector(_setDoublePage:)), [NSNumber numberWithInt:WebMenuItemPDFFacingPagesScrolling], NSStringFromSelector(@selector(_setDoublePageScrolling:)), [NSNumber numberWithInt:WebMenuItemPDFContinuous], NSStringFromSelector(@selector(_toggleContinuous:)), [NSNumber numberWithInt:WebMenuItemPDFNextPage], NSStringFromSelector(@selector(goToNextPage:)), [NSNumber numberWithInt:WebMenuItemPDFPreviousPage], NSStringFromSelector(@selector(goToPreviousPage:)), nil]; // Leave these menu items out, since WebKit inserts equivalent ones. Note that we leave out PDFKit's "Look Up in Dictionary" // item here because WebKit already includes an item with the same title and purpose. We map WebKit's to PDFKit's // "Look Up in Dictionary" via the implementation of -[WebPDFView _lookUpInDictionaryFromMenu:]. NSSet *unwantedActions = [[NSSet alloc] initWithObjects: NSStringFromSelector(@selector(_searchInSpotlight:)), NSStringFromSelector(@selector(_searchInGoogle:)), NSStringFromSelector(@selector(_searchInDictionary:)), NSStringFromSelector(@selector(copy:)), nil]; NSEnumerator *e = [[[PDFSubview menuForEvent:theEvent] itemArray] objectEnumerator]; NSMenuItem *item; while ((item = [e nextObject]) != nil) { NSString *actionString = NSStringFromSelector([item action]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -