Patch by Trey Matteson <trey@usa.net>
authorsullivan <sullivan@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 1 Aug 2005 17:50:35 +0000 (17:50 +0000)
committersullivan <sullivan@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 1 Aug 2005 17:50:35 +0000 (17:50 +0000)
        Reviewed by me.

        Fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=4014
          PDF files by default load with a poor choice of sizing

        For now the various PDF viewing settings are sticky, stored in 2 new defaults.  Since
        there are a number of ways these settings are changed, I made a proxy for the PDFView
        through which all view changing messages are sent.  The proxy adds the behavior of
        updating the defaults upon any change.

        * Misc.subproj/WebNSDictionaryExtras.h:
        * Misc.subproj/WebNSDictionaryExtras.m:
        (-[NSMutableDictionary _webkit_setFloat:forKey:]):  New support method.
        * WebView.subproj/WebPDFView.h:
        * WebView.subproj/WebPDFView.m:
        (-[WebPDFView initWithFrame:]):  Create proxy for PDFView.
        (-[WebPDFView dealloc]):  Free proxy.
        (-[WebPDFView _menuItemsFromPDFKitForEvent:]):  For relevant context menu items, set the
            target to the proxy instead of the PDFView.
        (-[WebPDFView _readPDFDefaults]):  Init PDFView with settings from defaults.
        (-[WebPDFView layout]):  Call _readPDFDefaults, once.  This turned out to be the best hook.
        (-[WebPDFView _makeTextSmaller:]):  Change PDFView via proxy
        (-[WebPDFView _makeTextLarger:]):  Ditto
        (-[WebPDFView _makeTextStandardSize:]):  Ditto
        (-[PDFPrefUpdatingProxy initWithView:]):  trivial
        (-[PDFPrefUpdatingProxy forwardInvocation:]):  Forward the msg, then update defaults
        (-[PDFPrefUpdatingProxy methodSignatureForSelector:]):  Simple forwarding support.
        * WebView.subproj/WebPreferenceKeysPrivate.h:
        * WebView.subproj/WebPreferences.m:
        (+[WebPreferences initialize]):  Set initial values for new PDF viewing defaults.
        (-[WebPreferences _integerValueForKey:]):  Nuke stray comment.
        (-[WebPreferences _floatValueForKey:]):  New simple support method.
        (-[WebPreferences _setFloatValue:forKey:]):  Ditto.
        (-[WebPreferences PDFScaleFactor]):  4 accessors for new defaults
        (-[WebPreferences setPDFScaleFactor:]):
        (-[WebPreferences PDFDisplayMode]):
        (-[WebPreferences setPDFDisplayMode:]):
        * WebView.subproj/WebPreferencesPrivate.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@9996 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKit/ChangeLog
WebKit/Misc.subproj/WebNSDictionaryExtras.h
WebKit/Misc.subproj/WebNSDictionaryExtras.m
WebKit/WebView.subproj/WebPDFView.h
WebKit/WebView.subproj/WebPDFView.m
WebKit/WebView.subproj/WebPreferenceKeysPrivate.h
WebKit/WebView.subproj/WebPreferences.m
WebKit/WebView.subproj/WebPreferencesPrivate.h

index 0da211c..0527841 100644 (file)
@@ -1,3 +1,45 @@
+2005-07-31  John Sullivan  <sullivan@apple.com>
+
+        Patch by Trey Matteson <trey@usa.net>
+        Reviewed by me.
+
+        Fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=4014
+          PDF files by default load with a poor choice of sizing
+
+        For now the various PDF viewing settings are sticky, stored in 2 new defaults.  Since
+        there are a number of ways these settings are changed, I made a proxy for the PDFView
+        through which all view changing messages are sent.  The proxy adds the behavior of
+        updating the defaults upon any change.
+
+        * Misc.subproj/WebNSDictionaryExtras.h:
+        * Misc.subproj/WebNSDictionaryExtras.m:
+        (-[NSMutableDictionary _webkit_setFloat:forKey:]):  New support method.
+        * WebView.subproj/WebPDFView.h:
+        * WebView.subproj/WebPDFView.m:
+        (-[WebPDFView initWithFrame:]):  Create proxy for PDFView.
+        (-[WebPDFView dealloc]):  Free proxy.
+        (-[WebPDFView _menuItemsFromPDFKitForEvent:]):  For relevant context menu items, set the
+            target to the proxy instead of the PDFView.
+        (-[WebPDFView _readPDFDefaults]):  Init PDFView with settings from defaults.
+        (-[WebPDFView layout]):  Call _readPDFDefaults, once.  This turned out to be the best hook.
+        (-[WebPDFView _makeTextSmaller:]):  Change PDFView via proxy
+        (-[WebPDFView _makeTextLarger:]):  Ditto
+        (-[WebPDFView _makeTextStandardSize:]):  Ditto
+        (-[PDFPrefUpdatingProxy initWithView:]):  trivial
+        (-[PDFPrefUpdatingProxy forwardInvocation:]):  Forward the msg, then update defaults
+        (-[PDFPrefUpdatingProxy methodSignatureForSelector:]):  Simple forwarding support.
+        * WebView.subproj/WebPreferenceKeysPrivate.h:
+        * WebView.subproj/WebPreferences.m:
+        (+[WebPreferences initialize]):  Set initial values for new PDF viewing defaults.
+        (-[WebPreferences _integerValueForKey:]):  Nuke stray comment.
+        (-[WebPreferences _floatValueForKey:]):  New simple support method.
+        (-[WebPreferences _setFloatValue:forKey:]):  Ditto.
+        (-[WebPreferences PDFScaleFactor]):  4 accessors for new defaults 
+        (-[WebPreferences setPDFScaleFactor:]):
+        (-[WebPreferences PDFDisplayMode]):
+        (-[WebPreferences setPDFDisplayMode:]):
+        * WebView.subproj/WebPreferencesPrivate.h:
+
 2005-08-01  Justin Garcia  <justin.garcia@apple.com>
 
         Patch by Trey Matteson <trey@usa.net>
index 1a45854..8b532bc 100644 (file)
@@ -39,6 +39,7 @@
 @interface NSMutableDictionary (WebNSDictionaryExtras)
 - (void)_webkit_setObject:(id)object forUncopiedKey:(id)key;
 - (void)_webkit_setInt:(int)value forKey:(id)key;
+- (void)_webkit_setFloat:(float)value forKey:(id)key;
 - (void)_webkit_setBool:(BOOL)value forKey:(id)key;
 @end
 
index a200f76..ca356cd 100644 (file)
     [object release];
 }
 
+-(void)_webkit_setFloat:(float)value forKey:(id)key
+{
+    NSNumber *object = [[NSNumber alloc] initWithFloat:value];
+    [self setObject:object forKey:key];
+    [object release];
+}
+
 -(void)_webkit_setBool:(BOOL)value forKey:(id)key
 {
     NSNumber *object = [[NSNumber alloc] initWithBool:value];
index f20b1b0..840e91a 100644 (file)
@@ -30,6 +30,7 @@
 
 @class PDFView;
 @class WebDataSource;
+@class PDFPrefUpdatingProxy;
 
 @protocol _WebDocumentTextSizing;
 @protocol _WebDocumentViewState;
@@ -42,6 +43,8 @@
     WebDataSource *dataSource;
     NSString *path;
     BOOL written;
+    BOOL firstLayoutDone;
+    PDFView *PDFSubviewProxy;
 }
 
 + (NSBundle *)PDFKitBundle;
index a57aca7..6534416 100644 (file)
@@ -43,6 +43,7 @@
 #import <WebKit/WebUIDelegate.h>
 #import <WebKit/WebView.h>
 #import <WebKit/WebViewPrivate.h>
+#import <WebKit/WebPreferencesPrivate.h>
 
 #import <WebKitSystemInterface.h>
 #import <PDFKit/PDFKit.h>
 // QuartzPrivate.h doesn't include the PDFKit private headers, so we can't get at PDFViewPriv.h. (3957971)
 // Even if that was fixed, we'd have to tweak compile options to include QuartzPrivate.h. (3957839)
 
+// This 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
+
 @interface PDFDocument (PDFKitSecretsIKnow)
 - (NSPrintOperation *)getPrintOperationForPrintInfo:(NSPrintInfo *)printInfo autoRotate:(BOOL)doRotate;
 @end
@@ -97,6 +106,10 @@ NSString *_NSPathForSystemFramework(NSString *framework);
         [self addSubview:PDFSubview];
         [PDFSubview setDelegate:self];
         written = NO;
+        firstLayoutDone = 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;
 }
@@ -105,6 +118,7 @@ NSString *_NSPathForSystemFramework(NSString *framework);
 {
     [PDFSubview release];
     [path release];
+    [PDFSubviewProxy release];
     [super dealloc];
 }
 
@@ -243,6 +257,11 @@ static void applicationInfoForMIMEType(NSString *type, NSString **name, NSImage
         }
         if ([itemCopy tag] == 0) {
             [itemCopy setTag:tag];
+            if ([itemCopy target] == PDFSubview) {
+                // Note that updating the defaults is cheap because it catches redundant settings, so installing
+                // the proxy for actions that don't impact the defaults is OK
+                [itemCopy setTarget:PDFSubviewProxy];
+            }
         } else {
             ERROR("PDF context menu item %@ came with tag %d, so no WebKit tag was applied. This could mean that the item doesn't appear in clients such as Safari.", [itemCopy title], [itemCopy tag]);
         }
@@ -333,6 +352,20 @@ static void applicationInfoForMIMEType(NSString *type, NSString **name, NSImage
     [self setFrame:[[self superview] frame]];
 }
 
+- (void)_readPDFDefaults
+{
+    // Set up default viewing params
+    WebPreferences *prefs = [[self _webView] preferences];
+    float scaleFactor = [prefs PDFScaleFactor];
+    if (scaleFactor == 0) {
+        [PDFSubview setAutoScales:YES];
+    } else {
+        [PDFSubview setAutoScales:NO];
+        [PDFSubview setScaleFactor:scaleFactor];
+    }
+    [PDFSubview setDisplayMode:[prefs PDFDisplayMode]];    
+}
+
 - (void)dataSourceUpdated:(WebDataSource *)dataSource
 {
 }
@@ -343,6 +376,14 @@ static void applicationInfoForMIMEType(NSString *type, NSString **name, NSImage
 
 - (void)layout
 {
+    if (!firstLayoutDone) {
+        firstLayoutDone = YES;
+        // Be wary of moving the point where we do this restore.  PDFKit apparently has some ordering issues
+        // as to when this is done.  For example, if you do it in this class' init method, it sometimes has no
+        // effect.  When I tried it in setDataSource:, the window got in a weird state where no more drawing
+        // ever occurred, but the app was not hung.
+        [self _readPDFDefaults];
+    }
 }
 
 - (void)viewWillMoveToHostWindow:(NSWindow *)hostWindow
@@ -597,17 +638,17 @@ static BOOL PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *select
 
 - (IBAction)_makeTextSmaller:(id)sender
 {
-    [PDFSubview zoomOut:sender];
+    [PDFSubviewProxy zoomOut:sender];
 }
 
 - (IBAction)_makeTextLarger:(id)sender
 {
-    [PDFSubview zoomIn:sender];
+    [PDFSubviewProxy zoomIn:sender];
 }
 
 - (IBAction)_makeTextStandardSize:(id)sender
 {
-    [PDFSubview setScaleFactor:1.0];
+    [PDFSubviewProxy setScaleFactor:1.0];
 }
 
 - (BOOL)_tracksCommonSizeFactor
@@ -681,4 +722,31 @@ static BOOL PDFSelectionsAreEqual(PDFSelection *selectionA, PDFSelection *select
 
 @end
 
+@implementation PDFPrefUpdatingProxy
+
+- (id)initWithView:(WebPDFView *)aView
+{
+    // No [super init], since we inherit from NSProxy
+    view = aView;
+    return self;
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation
+{
+    PDFView *PDFSubview = [view PDFSubview];
+    [invocation invokeWithTarget:PDFSubview];
+
+    WebPreferences *prefs = [[view _webView] preferences];
+    float scaleFactor = [PDFSubview autoScales] ? 0.0 : [PDFSubview scaleFactor];
+    [prefs setPDFScaleFactor:scaleFactor];
+    [prefs setPDFDisplayMode:[PDFSubview displayMode]];
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
+{
+    return [[view PDFSubview] methodSignatureForSelector:sel];
+}
+
+@end
+
 #endif // OMIT_TIGER_FEATURES
index 76b075d..875c051 100644 (file)
@@ -62,3 +62,5 @@
 // cover methods themselves are private.
 #define WebKitRespectStandardStyleKeyEquivalentsPreferenceKey @"WebKitRespectStandardStyleKeyEquivalents"
 #define WebKitShowsURLsInToolTipsPreferenceKey @"WebKitShowsURLsInToolTips"
+#define WebKitPDFDisplayModePreferenceKey @"WebKitPDFDisplayMode"
+#define WebKitPDFScaleFactorPreferenceKey @"WebKitPDFScaleFactor"
index 98c7f4b..03cf7db 100644 (file)
@@ -73,6 +73,10 @@ enum { WebPreferencesVersion = 1 };
 // without being in the public header file.
 - (BOOL)_boolValueForKey:(NSString *)key;
 - (void)_setBoolValue:(BOOL)value forKey:(NSString *)key;
+- (int)_integerValueForKey:(NSString *)key;
+- (void)_setIntegerValue:(int)value forKey:(NSString *)key;
+- (float)_floatValueForKey:(NSString *)key;
+- (void)_setFloatValue:(float)value forKey:(NSString *)key;
 @end
 
 @implementation WebPreferences
@@ -226,8 +230,12 @@ NS_ENDHANDLER
         [NSNumber numberWithBool:NO],   WebKitPrivateBrowsingEnabledPreferenceKey,
         [NSNumber numberWithBool:NO],   WebKitRespectStandardStyleKeyEquivalentsPreferenceKey,
         [NSNumber numberWithBool:NO],   WebKitShowsURLsInToolTipsPreferenceKey,
+        @"1",                           WebKitPDFDisplayModePreferenceKey,
+        @"1.0",                         WebKitPDFScaleFactorPreferenceKey,
         nil];
 
+    // This value shouldn't ever change, which is assumed in the initialization of WebKitPDFDisplayModePreferenceKey above
+    ASSERT(kPDFDisplaySinglePageContinuous == 1);
     [[NSUserDefaults standardUserDefaults] registerDefaults:dict];
 }
 
@@ -274,7 +282,6 @@ NS_ENDHANDLER
 - (int)_integerValueForKey:(NSString *)key
 {
     id o = [self _valueForKey:key];
-    // 
     return [o respondsToSelector:@selector(intValue)] ? [o intValue] : 0;
 }
 
@@ -289,6 +296,23 @@ NS_ENDHANDLER
     [self _postPreferencesChangesNotification];
 }
 
+- (float)_floatValueForKey:(NSString *)key
+{
+    id o = [self _valueForKey:key];
+    return [o respondsToSelector:@selector(floatValue)] ? [o floatValue] : 0.0;
+}
+
+- (void)_setFloatValue:(float)value forKey:(NSString *)key
+{
+    if ([self _floatValueForKey:key] == value)
+        return;
+    NSString *_key = KEY(key);
+    [_private->values _webkit_setFloat:value forKey:_key];
+    if (_private->autosaves)
+        [[NSUserDefaults standardUserDefaults] setFloat:value forKey:_key];
+    [self _postPreferencesChangesNotification];
+}
+
 - (BOOL)_boolValueForKey:(NSString *)key
 {
     return [self _integerValueForKey:key] != 0;
@@ -609,6 +633,31 @@ NS_ENDHANDLER
     return (NSTimeInterval)[[NSUserDefaults standardUserDefaults] floatForKey:WebKitBackForwardCacheExpirationIntervalKey];
 }
 
+- (float)PDFScaleFactor
+{
+    return [self _floatValueForKey:WebKitPDFScaleFactorPreferenceKey];
+}
+
+- (void)setPDFScaleFactor:(float)factor
+{
+    [self _setFloatValue:factor forKey:WebKitPDFScaleFactorPreferenceKey];
+}
+
+- (PDFDisplayMode)PDFDisplayMode;
+{
+    PDFDisplayMode value = [self _integerValueForKey:WebKitPDFDisplayModePreferenceKey];
+    if (value != kPDFDisplaySinglePage && value != kPDFDisplaySinglePageContinuous && value != kPDFDisplayTwoUp && value != kPDFDisplayTwoUpContinuous) {
+        // protect against new modes from future versions of OS X stored in defaults
+        value = kPDFDisplaySinglePageContinuous;
+    }
+    return value;
+}
+
+- (void)setPDFDisplayMode:(PDFDisplayMode)mode
+{
+    [self _setIntegerValue:mode forKey:WebKitPDFDisplayModePreferenceKey];
+}
+
 static NSMutableDictionary *webPreferencesInstances = nil;
 
 + (WebPreferences *)_getInstanceForIdentifier:(NSString *)ident
index a2bb6c3..ef63b17 100644 (file)
 
 #import <WebKit/WebPreferences.h>
 
+#import <PDFKit/PDFView.h>
+// NOTE: #importing Quartz/Quartz.h causes an ambiguous signature conflict anywhere the method "count" is used.
+// To avoid this, we #import just this specific header. For this to work, the project's Framework Search Paths
+// has been modified to include /System/Library/Frameworks/Quartz.framework/Frameworks. Clients that include 
+// this file may have to do this same trick.
+
 @interface WebPreferences (WebPrivate)
 
 // Preferences that might be public in a future release
 - (BOOL)textAreasAreResizable;
 - (void)setTextAreasAreResizable:(BOOL)flag;
 
+- (PDFDisplayMode)PDFDisplayMode;
+- (void)setPDFDisplayMode:(PDFDisplayMode)mode;
+
+// zero means do AutoScale
+- (float)PDFScaleFactor;
+- (void)setPDFScaleFactor:(float)scale;
+
 // Other private methods
 - (int)_pageCacheSize;
 - (int)_objectCacheSize;
@@ -51,4 +64,5 @@
 + (CFStringEncoding)_systemCFStringEncoding;
 + (void)_setInitialDefaultTextEncodingToSystemEncoding;
 + (void)_setIBCreatorID:(NSString *)string;
+
 @end