⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 webpdfview.mm

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 MM
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1.  Redistributions of source code must retain the above copyright *     notice, this list of conditions and the following disclaimer.  * 2.  Redistributions in binary form must reproduce the above copyright *     notice, this list of conditions and the following disclaimer in the *     documentation and/or other materials provided with the distribution.  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of *     its contributors may be used to endorse or promote products derived *     from this software without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#import "WebPDFView.h"#import "WebDataSourceInternal.h"#import "WebDocumentInternal.h"#import "WebDocumentPrivate.h"#import "WebFrame.h"#import "WebFrameInternal.h"#import "WebFrameView.h"#import "WebLocalizableStrings.h"#import "WebNSArrayExtras.h"#import "WebNSAttributedStringExtras.h"#import "WebNSPasteboardExtras.h"#import "WebNSViewExtras.h"#import "WebPDFRepresentation.h"#import "WebPreferencesPrivate.h"#import "WebUIDelegate.h"#import "WebUIDelegatePrivate.h"#import "WebView.h"#import "WebViewInternal.h"#import <PDFKit/PDFKit.h>#import <WebCore/EventNames.h>#import <WebCore/Frame.h>#import <WebCore/FrameLoader.h>#import <WebCore/FrameLoadRequest.h>#import <WebCore/KURL.h>#import <WebCore/KeyboardEvent.h>#import <WebCore/MouseEvent.h>#import <WebCore/PlatformKeyboardEvent.h>#import <wtf/Assertions.h>using namespace WebCore;// Redeclarations of PDFKit notifications. We can't use the API since we use a weak link to the framework.#define _webkit_PDFViewDisplayModeChangedNotification @"PDFViewDisplayModeChanged"#define _webkit_PDFViewScaleChangedNotification @"PDFViewScaleChanged"#define _webkit_PDFViewPageChangedNotification @"PDFViewChangedPage"@interface PDFDocument (PDFKitSecretsIKnow)- (NSPrintOperation *)getPrintOperationForPrintInfo:(NSPrintInfo *)printInfo autoRotate:(BOOL)doRotate;@endextern "C" NSString *_NSPathForSystemFramework(NSString *framework);@interface WebPDFView (FileInternal)+ (Class)_PDFPreviewViewClass;+ (Class)_PDFViewClass;- (BOOL)_anyPDFTagsFoundInMenu:(NSMenu *)menu;- (void)_applyPDFDefaults;- (BOOL)_canLookUpInDictionary;- (NSClipView *)_clipViewForPDFDocumentView;- (NSEvent *)_fakeKeyEventWithFunctionKey:(unichar)functionKey;- (NSMutableArray *)_menuItemsFromPDFKitForEvent:(NSEvent *)theEvent;- (PDFSelection *)_nextMatchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag fromSelection:(PDFSelection *)initialSelection startInSelection:(BOOL)startInSelection;- (void)_openWithFinder:(id)sender;- (NSString *)_path;- (void)_PDFDocumentViewMightHaveScrolled:(NSNotification *)notification;- (BOOL)_pointIsInSelection:(NSPoint)point;- (NSAttributedString *)_scaledAttributedString:(NSAttributedString *)unscaledAttributedString;- (void)_setTextMatches:(NSArray *)array;- (NSString *)_temporaryPDFDirectoryPath;- (void)_trackFirstResponder;- (void)_updatePreferencesSoon;- (NSSet *)_visiblePDFPages;@end;// PDFPrefUpdatingProxy is a class that forwards everything it gets to a target and updates the PDF viewing prefs// after each of those messages.  We use it as a way to hook all the places that the PDF viewing attrs change.@interface PDFPrefUpdatingProxy : NSProxy {    WebPDFView *view;}- (id)initWithView:(WebPDFView *)view;@end#pragma mark C UTILITY FUNCTIONSstatic void _applicationInfoForMIMEType(NSString *type, NSString **name, NSImage **image){    NSURL *appURL = nil;        OSStatus error = LSCopyApplicationForMIMEType((CFStringRef)type, kLSRolesAll, (CFURLRef *)&appURL);    if (error != noErr)        return;        NSString *appPath = [appURL path];    CFRelease (appURL);        *image = [[NSWorkspace sharedWorkspace] iconForFile:appPath];      [*image setSize:NSMakeSize(16.f,16.f)];          NSString *appName = [[NSFileManager defaultManager] displayNameAtPath:appPath];    *name = appName;}// FIXME 4182876: We can eliminate this function in favor if -isEqual: if [PDFSelection isEqual:] is overridden// to compare contents.static BOOL _PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *selectionB){    NSArray *aPages = [selectionA pages];    NSArray *bPages = [selectionB pages];        if (![aPages isEqual:bPages])        return NO;        int count = [aPages count];    int i;    for (i = 0; i < count; ++i) {        NSRect aBounds = [selectionA boundsForPage:[aPages objectAtIndex:i]];        NSRect bBounds = [selectionB boundsForPage:[bPages objectAtIndex:i]];        if (!NSEqualRects(aBounds, bBounds)) {            return NO;        }    }        return YES;}@implementation WebPDFView#pragma mark WebPDFView API+ (NSBundle *)PDFKitBundle{    static NSBundle *PDFKitBundle = nil;    if (PDFKitBundle == nil) {        NSString *PDFKitPath = [_NSPathForSystemFramework(@"Quartz.framework") stringByAppendingString:@"/Frameworks/PDFKit.framework"];        if (PDFKitPath == nil) {            LOG_ERROR("Couldn't find PDFKit.framework");            return nil;        }        PDFKitBundle = [NSBundle bundleWithPath:PDFKitPath];        if (![PDFKitBundle load]) {            LOG_ERROR("Couldn't load PDFKit.framework");        }    }    return PDFKitBundle;}+ (NSArray *)supportedMIMETypes{    return [WebPDFRepresentation supportedMIMETypes];}- (void)setPDFDocument:(PDFDocument *)doc{    // Both setDocument: and _applyPDFDefaults will trigger scale and mode-changed notifications.    // Those aren't reflecting user actions, so we need to ignore them.    _ignoreScaleAndDisplayModeAndPageNotifications = YES;    [PDFSubview setDocument:doc];    [self _applyPDFDefaults];    _ignoreScaleAndDisplayModeAndPageNotifications = NO;}#pragma mark NSObject OVERRIDES- (void)dealloc{    ASSERT(!trackedFirstResponder);    [dataSource release];    [previewView release];    [PDFSubview release];    [path release];    [PDFSubviewProxy release];    [textMatches release];    [super dealloc];}#pragma mark NSResponder OVERRIDES- (void)centerSelectionInVisibleArea:(id)sender{    [PDFSubview scrollSelectionToVisible:nil];}- (void)scrollPageDown:(id)sender{    // PDFView doesn't support this responder method directly, so we pass it a fake key event    [PDFSubview keyDown:[self _fakeKeyEventWithFunctionKey:NSPageDownFunctionKey]];}- (void)scrollPageUp:(id)sender{    // PDFView doesn't support this responder method directly, so we pass it a fake key event    [PDFSubview keyDown:[self _fakeKeyEventWithFunctionKey:NSPageUpFunctionKey]];}- (void)scrollLineDown:(id)sender{    // PDFView doesn't support this responder method directly, so we pass it a fake key event    [PDFSubview keyDown:[self _fakeKeyEventWithFunctionKey:NSDownArrowFunctionKey]];}- (void)scrollLineUp:(id)sender{    // PDFView doesn't support this responder method directly, so we pass it a fake key event    [PDFSubview keyDown:[self _fakeKeyEventWithFunctionKey:NSUpArrowFunctionKey]];}- (void)scrollToBeginningOfDocument:(id)sender{    // PDFView doesn't support this responder method directly, so we pass it a fake key event    [PDFSubview keyDown:[self _fakeKeyEventWithFunctionKey:NSHomeFunctionKey]];}- (void)scrollToEndOfDocument:(id)sender{    // PDFView doesn't support this responder method directly, so we pass it a fake key event    [PDFSubview keyDown:[self _fakeKeyEventWithFunctionKey:NSEndFunctionKey]];}// jumpToSelection is the old name for what AppKit now calls centerSelectionInVisibleArea. Safari// was using the old jumpToSelection selector in its menu. Newer versions of Safari will us the// selector centerSelectionInVisibleArea. We'll leave this old selector in place for two reasons:// (1) compatibility between older Safari and newer WebKit; (2) other WebKit-based applications// might be using the jumpToSelection: selector, and we don't want to break them.- (void)jumpToSelection:(id)sender{    [self centerSelectionInVisibleArea:nil];}#pragma mark NSView OVERRIDES- (BOOL)acceptsFirstResponder {    return YES;}- (BOOL)becomeFirstResponder{    // This works together with setNextKeyView to splice our PDFSubview into    // the key loop similar to the way NSScrollView does this.    NSWindow *window = [self window];    id newFirstResponder = nil;        if ([window keyViewSelectionDirection] == NSSelectingPrevious) {        NSView *previousValidKeyView = [self previousValidKeyView];        if ((previousValidKeyView != self) && (previousValidKeyView != PDFSubview))            newFirstResponder = previousValidKeyView;    } else {        NSView *PDFDocumentView = [PDFSubview documentView];        if ([PDFDocumentView acceptsFirstResponder])            newFirstResponder = PDFDocumentView;    }        if (!newFirstResponder)        return NO;        if (![window makeFirstResponder:newFirstResponder])        return NO;        [[dataSource webFrame] _clearSelectionInOtherFrames];        return YES;}- (NSView *)hitTest:(NSPoint)point{    // Override hitTest so we can override menuForEvent.    NSEvent *event = [NSApp currentEvent];    NSEventType type = [event type];    if (type == NSRightMouseDown || (type == NSLeftMouseDown && ([event modifierFlags] & NSControlKeyMask)))        return self;    return [super hitTest:point];}- (id)initWithFrame:(NSRect)frame{    self = [super initWithFrame:frame];    if (self) {        [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];                Class previewViewClass = [[self class] _PDFPreviewViewClass];                // We might not have found a previewViewClass, but if we did find it        // then we should be able to create an instance.        if (previewViewClass) {            previewView = [[previewViewClass alloc] initWithFrame:frame];            ASSERT(previewView);        }                NSView *topLevelPDFKitView = nil;        if (previewView) {            // We'll retain the PDFSubview here so that it is equally retained in all            // code paths. That way we don't need to worry about conditionally releasing            // it later.            PDFSubview = [[previewView performSelector:@selector(pdfView)] retain];            topLevelPDFKitView = previewView;        } else {            PDFSubview = [[[[self class] _PDFViewClass] alloc] initWithFrame:frame];            topLevelPDFKitView = PDFSubview;        }                ASSERT(PDFSubview);                [topLevelPDFKitView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];        [self addSubview:topLevelPDFKitView];                [PDFSubview setDelegate:self];        written = NO;        // Messaging this proxy is the same as messaging PDFSubview, with the side effect that the        // PDF viewing defaults are updated afterwards        PDFSubviewProxy = (PDFView *)[[PDFPrefUpdatingProxy alloc] initWithView:self];    }        return self;}- (NSMenu *)menuForEvent:(NSEvent *)theEvent{    // Start with the menu items supplied by PDFKit, with WebKit tags applied    NSMutableArray *items = [self _menuItemsFromPDFKitForEvent:theEvent];        // Add in an "Open with <default PDF viewer>" item    NSString *appName = nil;    NSImage *appIcon = nil;        _applicationInfoForMIMEType([[dataSource response] MIMEType], &appName, &appIcon);    if (!appName)        appName = UI_STRING("Finder", "Default application name for Open With context menu");        // To match the PDFKit style, we'll add Open with Preview even when there's no document yet to view, and    // disable it using validateUserInterfaceItem.    NSString *title = [NSString stringWithFormat:UI_STRING("Open with %@", "context menu item for PDF"), appName];    NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:title action:@selector(_openWithFinder:) keyEquivalent:@""];    [item setTag:WebMenuItemTagOpenWithDefaultApplication];    if (appIcon)        [item setImage:appIcon];    [items insertObject:item atIndex:0];    [item release];        [items insertObject:[NSMenuItem separatorItem] atIndex:1];        // pass the items off to the WebKit context menu mechanism    WebView *webView = [[dataSource webFrame] webView];    ASSERT(webView);    NSMenu *menu = [webView _menuForElement:[self elementAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]] defaultItems:items];        // The delegate has now had the opportunity to add items to the standard PDF-related items, or to    // remove or modify some of the PDF-related items. In 10.4, the PDF context menu did not go through     // the standard WebKit delegate path, and so the standard PDF-related items always appeared. For    // clients that create their own context menu by hand-picking specific items from the default list, such as    // Safari, none of the PDF-related items will appear until the client is rewritten to explicitly    // include these items. For backwards compatibility of tip-of-tree WebKit with the 10.4 version of Safari    // (the configuration that people building open source WebKit use), we'll use the entire set of PDFKit-supplied    // menu items. This backward-compatibility hack won't work with any non-Safari clients, but this seems OK since

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -