Reviewed by Chris Blumenberg.
authorsullivan <sullivan@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Jun 2005 21:32:09 +0000 (21:32 +0000)
committersullivan <sullivan@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Jun 2005 21:32:09 +0000 (21:32 +0000)
        - fixed <rdar://problem/3764645> please add a way to allow WebKit clients to override the WebPDFView context menu

        * PublicHeaderChangesFromTiger.txt: Added.
        New file to keep track of changes made to public headers that haven't been through API review yet.
        Initially lists the WebMenuItem enum tags added to WebUIDelegate.h as part of this change.

        * WebView.subproj/WebDefaultContextMenuDelegate.m:
        (-[WebDefaultUIDelegate appendDefaultItems:toArray:]):
        new method, handles initial separator
        (-[WebDefaultUIDelegate contextMenuItemsForElement:defaultMenuItems:]):
        now has defaultMenuItems: parameter. Any menu items in this array are appended at the end of
        the standard set.
        (-[WebDefaultUIDelegate editingContextMenuItemsForElement:defaultMenuItems:]):
        ditto
        (-[WebDefaultUIDelegate webView:contextMenuItemsForElement:defaultMenuItems:]):
        This had a defaultMenuItems parameter before but it was always nil. Now it passes the defaultMenuItems
        parameter on to the two methods that construct lists (one for editing, the other for viewing). Also
        tweaked variable name and type for clarity.

        * WebView.subproj/WebHTMLView.m:
        (-[WebHTMLView menuForEvent:]):
        passes nil for new defaultItems parameter of _menuForElement:

        * WebView.subproj/WebImageView.m:
        (-[WebImageView menuForEvent:]):
        ditto

        * WebView.subproj/WebTextView.m:
        (-[WebTextView menuForEvent:]):
        ditto

        * WebView.subproj/WebPDFView.m:
        (-[WebPDFView elementAtPoint:]):
        new method to create the element dictionary needed for _menuForElement:defaultItems:. Only supplies the
        webFrame at this point.
        (-[WebPDFView _menuItemsFromPDFKitForEvent:]):
        new method to return copies of the menu items that PDFKit would include in the context menu, with
        WebKit tags applied
        (-[WebPDFView menuForEvent:]):
        now calls standard WebKit context menu mechanism, so clients' delegates can modify the context menu as
        desired. The initial set of items are the ones WebKit was already displaying for PDF context menus.

        * WebView.subproj/WebUIDelegate.h:
        added enum values for the menu items in the PDF context menu

        * WebView.subproj/WebViewPrivate.h:
        * WebView.subproj/WebView.m:
        (-[WebView _menuForElement:defaultItems:]):
        Added the defaultItems: parameter to this method, which is then passed along to WebDefaultUIDelegate.
        All callers pass nil except for WebPDFView, at least for now.

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

WebKit/ChangeLog
WebKit/PublicHeaderChangesFromTiger.txt [new file with mode: 0644]
WebKit/WebView.subproj/WebDefaultContextMenuDelegate.m
WebKit/WebView.subproj/WebHTMLView.m
WebKit/WebView.subproj/WebImageView.m
WebKit/WebView.subproj/WebPDFView.m
WebKit/WebView.subproj/WebTextView.m
WebKit/WebView.subproj/WebUIDelegate.h
WebKit/WebView.subproj/WebView.m
WebKit/WebView.subproj/WebViewPrivate.h

index 8b08a06..2a83a1b 100644 (file)
@@ -1,3 +1,58 @@
+2005-06-22  John Sullivan  <sullivan@apple.com>
+
+        Reviewed by Chris Blumenberg.
+        
+        - fixed <rdar://problem/3764645> please add a way to allow WebKit clients to override the WebPDFView context menu
+
+        * PublicHeaderChangesFromTiger.txt: Added.
+        New file to keep track of changes made to public headers that haven't been through API review yet.
+        Initially lists the WebMenuItem enum tags added to WebUIDelegate.h as part of this change.
+        
+        * WebView.subproj/WebDefaultContextMenuDelegate.m:
+        (-[WebDefaultUIDelegate appendDefaultItems:toArray:]):
+        new method, handles initial separator
+        (-[WebDefaultUIDelegate contextMenuItemsForElement:defaultMenuItems:]):
+        now has defaultMenuItems: parameter. Any menu items in this array are appended at the end of
+        the standard set.
+        (-[WebDefaultUIDelegate editingContextMenuItemsForElement:defaultMenuItems:]):
+        ditto
+        (-[WebDefaultUIDelegate webView:contextMenuItemsForElement:defaultMenuItems:]):
+        This had a defaultMenuItems parameter before but it was always nil. Now it passes the defaultMenuItems
+        parameter on to the two methods that construct lists (one for editing, the other for viewing). Also
+        tweaked variable name and type for clarity.
+        
+        * WebView.subproj/WebHTMLView.m:
+        (-[WebHTMLView menuForEvent:]):
+        passes nil for new defaultItems parameter of _menuForElement:
+        
+        * WebView.subproj/WebImageView.m:
+        (-[WebImageView menuForEvent:]):
+        ditto
+        
+        * WebView.subproj/WebTextView.m:
+        (-[WebTextView menuForEvent:]):
+        ditto
+
+        * WebView.subproj/WebPDFView.m:
+        (-[WebPDFView elementAtPoint:]):
+        new method to create the element dictionary needed for _menuForElement:defaultItems:. Only supplies the
+        webFrame at this point.
+        (-[WebPDFView _menuItemsFromPDFKitForEvent:]):
+        new method to return copies of the menu items that PDFKit would include in the context menu, with
+        WebKit tags applied
+        (-[WebPDFView menuForEvent:]):
+        now calls standard WebKit context menu mechanism, so clients' delegates can modify the context menu as
+        desired. The initial set of items are the ones WebKit was already displaying for PDF context menus.
+        
+        * WebView.subproj/WebUIDelegate.h:
+        added enum values for the menu items in the PDF context menu
+        
+        * WebView.subproj/WebViewPrivate.h:
+        * WebView.subproj/WebView.m:
+        (-[WebView _menuForElement:defaultItems:]):
+        Added the defaultItems: parameter to this method, which is then passed along to WebDefaultUIDelegate.
+        All callers pass nil except for WebPDFView, at least for now.
+
 2005-06-22  Darin Adler  <darin@apple.com>
 
         Change by Mitz Pettel.
diff --git a/WebKit/PublicHeaderChangesFromTiger.txt b/WebKit/PublicHeaderChangesFromTiger.txt
new file mode 100644 (file)
index 0000000..ff27926
--- /dev/null
@@ -0,0 +1,21 @@
+This file lists changes to WebKit public header files that have been made since WebKit-412, which shipped with Mac OS X 10.4. All of these changes will have to be approved by the Apple API approval process, or rolled out, before Apple ships a new version of WebKit.
+
+When you make changes to public header files, please update this file, in the same general style as the ChangeLog file (new entries at top).
+===============================================
+
+2005-06-22  John Sullivan  <sullivan@apple.com>
+
+Added the following values to the enum of WebMenuItem tags in WebUIDelegate.h:
+
+    WebMenuItemTagOpenWithDefaultApplication,
+    WebMenuItemPDFActualSize,
+    WebMenuItemPDFZoomIn,
+    WebMenuItemPDFZoomOut,
+    WebMenuItemPDFAutoSize,
+    WebMenuItemPDFSinglePage,
+    WebMenuItemPDFFacingPages,
+    WebMenuItemPDFContinuous,
+    WebMenuItemPDFNextPage,
+    WebMenuItemPDFPreviousPage,
+
+These are all used by the context menu for PDF documents.
index 8587dae..4c59e79 100644 (file)
@@ -182,8 +182,27 @@ static NSString *localizedMenuTitleFromAppKit(NSString *key, NSString *comment)
     return menuItem;
 }
 
-- (NSArray *)contextMenuItemsForElement:(NSDictionary *)element
+- (void)appendDefaultItems:(NSArray *)defaultItems toArray:(NSMutableArray *)menuItems
 {
+    ASSERT_ARG(menuItems, menuItems != nil);
+    if ([defaultItems count] > 0) {
+        ASSERT(![[menuItems lastObject] isSeparatorItem]);
+        if (![[defaultItems objectAtIndex:0] isSeparatorItem]) {
+            [menuItems addObject:[NSMenuItem separatorItem]];
+            
+            NSEnumerator *e = [defaultItems objectEnumerator];
+            NSMenuItem *item;
+            while ((item = [e nextObject]) != nil) {
+                [menuItems addObject:item];
+            }
+        }
+    }
+}
+
+- (NSArray *)contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems
+{
+    // The defaultMenuItems here are ones supplied by the WebDocumentView protocol implementation. WebPDFView is
+    // one case that has non-nil default items here.
     NSMutableArray *menuItems = [NSMutableArray array];
     
     NSURL *linkURL = [element objectForKey:WebElementLinkURLKey];
@@ -242,16 +261,19 @@ static NSString *localizedMenuTitleFromAppKit(NSString *key, NSString *comment)
         }
     }
     
+    // Add the default items at the end, if any, after a separator
+    [self appendDefaultItems:defaultMenuItems toArray:menuItems];
+
     // Attach element as the represented object to each item.
     [menuItems makeObjectsPerformSelector:@selector(setRepresentedObject:) withObject:element];
     
     return menuItems;
 }
 
-- (NSArray *)editingContextMenuItemsForElement:(NSDictionary *)element
+- (NSArray *)editingContextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems
 {
-    NSMenuItem *item;
     NSMutableArray *menuItems = [NSMutableArray array];
+    NSMenuItem *item;
     WebHTMLView *HTMLView = (WebHTMLView *)[[[element objectForKey:WebElementFrameKey] frameView] documentView];
     ASSERT([HTMLView isKindOfClass:[WebHTMLView class]]);
     
@@ -297,6 +319,7 @@ static NSString *localizedMenuTitleFromAppKit(NSString *key, NSString *comment)
             textViewMenuNib = [[NSNib alloc] initWithNibNamed:@"WebViewEditingContextMenu" bundle:[NSBundle bundleForClass:[self class]]];
         }
         [textViewMenuNib instantiateNibWithOwner:self topLevelObjects:nil];
+        ASSERT(defaultMenu != nil);
     }
     
     // Add tags to the menu items because this is what the WebUIDelegate expects.
@@ -312,6 +335,8 @@ static NSString *localizedMenuTitleFromAppKit(NSString *key, NSString *comment)
         } else if (action == @selector(paste:)) {
             tag = WebMenuItemTagPaste;
         } else {
+            // FIXME 4158153: we should supply tags for each known item so clients can make
+            // sensible decisions, like we do with PDF context menu items (see WebPDFView.m)
             tag = WebMenuItemTagOther;
         }
         [item setTag:tag];
@@ -319,16 +344,19 @@ static NSString *localizedMenuTitleFromAppKit(NSString *key, NSString *comment)
         [item release];
     }
     
+    // Add the default items at the end, if any, after a separator
+    [self appendDefaultItems:defaultMenuItems toArray:menuItems];
+        
     return menuItems;
 }
 
 - (NSArray *)webView:(WebView *)wv contextMenuItemsForElement:(NSDictionary *)element  defaultMenuItems:(NSArray *)defaultMenuItems
 {
-    WebHTMLView *HTMLView = (WebHTMLView *)[[[element objectForKey:WebElementFrameKey] frameView] documentView];
-    if ([HTMLView isKindOfClass:[WebHTMLView class]] && [HTMLView _isEditable]) {
-        return [self editingContextMenuItemsForElement:element];
+    NSView *documentView = [[[element objectForKey:WebElementFrameKey] frameView] documentView];
+    if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _isEditable]) {
+        return [self editingContextMenuItemsForElement:element defaultMenuItems:defaultMenuItems];
     } else {
-        return [self contextMenuItemsForElement:element];
+        return [self contextMenuItemsForElement:element defaultMenuItems:defaultMenuItems];
     }
 }
 
index 103f143..943e573 100644 (file)
@@ -2329,7 +2329,7 @@ static WebHTMLView *lastHitView = nil;
     }
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
     NSDictionary *element = [self elementAtPoint:point];
-    return [[self _webView] _menuForElement:element];
+    return [[self _webView] _menuForElement:element defaultItems:nil];
 }
 
 // Search from the end of the currently selected location, or from the beginning of the
index 67b5362..30318a7 100644 (file)
 {
     WebView *webView = [self webView];
     ASSERT(webView);
-    return [webView _menuForElement:[self elementAtPoint:NSZeroPoint]];
+    return [webView _menuForElement:[self elementAtPoint:NSZeroPoint] defaultItems:nil];
 }
 
 - (void)mouseDown:(NSEvent *)event
index 0e0ee65..53e5bc4 100644 (file)
@@ -35,7 +35,9 @@
 #import <WebKit/WebLocalizableStrings.h>
 #import <WebKit/WebNSPasteboardExtras.h>
 #import <WebKit/WebPDFView.h>
+#import <WebKit/WebUIDelegate.h>
 #import <WebKit/WebView.h>
+#import <WebKit/WebViewPrivate.h>
 
 #import <Quartz/Quartz.h>
 
@@ -126,7 +128,6 @@ static void applicationInfoForMIMEType(NSString *type, NSString **name, NSImage
     *name = appName;
 }
 
-
 - (NSString *)path
 {
     // Generate path once.
@@ -169,10 +170,72 @@ static void applicationInfoForMIMEType(NSString *type, NSString **name, NSImage
     return [super hitTest:point];
 }
 
-- (NSMenu *)menuForEvent:(NSEvent *)theEvent
+- (NSDictionary *)elementAtPoint:(NSPoint)point
+{
+    WebFrame *frame = [dataSource webFrame];
+    ASSERT(frame);
+
+    // FIXME 4158121: should determine whether the point is over a selection, and if so set WebElementIsSelectedKey
+    // as in WebTextView.m. Would need to convert coordinates, and make sure that the code that checks
+    // WebElementIsSelectedKey would work with PDF documents.
+    return [NSDictionary dictionaryWithObjectsAndKeys:
+        frame, WebElementFrameKey, nil];
+}
+
+- (NSMutableArray *)_menuItemsFromPDFKitForEvent:(NSEvent *)theEvent
 {
-    NSMenu *menu = [PDFSubview menuForEvent: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:WebMenuItemPDFFacingPages], NSStringFromSelector(@selector(_setDoublePage:)),
+        [NSNumber numberWithInt:WebMenuItemPDFContinuous], NSStringFromSelector(@selector(_toggleContinuous:)),
+        [NSNumber numberWithInt:WebMenuItemPDFNextPage], NSStringFromSelector(@selector(goToNextPage:)),
+        [NSNumber numberWithInt:WebMenuItemPDFPreviousPage], NSStringFromSelector(@selector(goToPreviousPage:)),
+        nil];
+    
+    NSEnumerator *e = [[[PDFSubview menuForEvent:theEvent] itemArray] objectEnumerator];
+    NSMenuItem *item;
+    while ((item = [e nextObject]) != nil) {
+        // Copy items since a menu item can be in only one menu at a time, and we don't
+        // want to modify the original menu supplied by PDFKit.
+        NSMenuItem *itemCopy = [item copy];
+        [copiedItems addObject:itemCopy];
+        
+        if ([itemCopy isSeparatorItem]) {
+            continue;
+        }
+        NSString *actionString = NSStringFromSelector([itemCopy action]);
+        NSNumber *tagNumber = [actionsToTags objectForKey:actionString];
+        
+        int tag;
+        if (tagNumber != nil) {
+            tag = [tagNumber intValue];
+        } else {
+            tag = WebMenuItemTagOther;
+            ERROR("no WebKit menu item tag found for PDF context menu item action \"%@\", using WebMenuItemTagOther", actionString);
+        }
+        if ([itemCopy tag] == 0) {
+            [itemCopy setTag:tag];
+        } 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]);
+        }        
+    }
+    
+    [actionsToTags release];
     
+    return copiedItems;
+}
+
+- (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;
     
@@ -180,15 +243,22 @@ static void applicationInfoForMIMEType(NSString *type, NSString **name, NSImage
     if (!appName)
         appName = UI_STRING("Finder", "Default application name for Open With context menu");
     
-    NSString *title = [NSString stringWithFormat:UI_STRING("Open with %@", "Open document using the Finder"), appName];
-    
-    NSMenuItem *item = [menu insertItemWithTitle:title action:@selector(openWithFinder:) keyEquivalent:@"" atIndex:0];
+    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];
-        
-    [menu insertItem:[NSMenuItem separatorItem] atIndex:1];
+    [items insertObject:item atIndex:0];
+    [item release];
+    
+    [items insertObject:[NSMenuItem separatorItem] atIndex:1];
     
-    return menu;
+    // pass the items off to the WebKit context menu mechanism
+    WebView *webView = [[dataSource webFrame] webView];
+    ASSERT(webView);
+    // Currently clicks anywhere in the PDF view are treated the same, so we just pass NSZeroPoint;
+    // we implement elementAtPoint: here just to be slightly forward-looking.
+    return [webView _menuForElement:[self elementAtPoint:NSZeroPoint] defaultItems:items];
 }
 
 - (void)_updateScalingToReflectTextSize
index c151a7b..fd7d735 100644 (file)
 {    
     WebView *webView = [self _web_parentWebView];
     ASSERT(webView);
-    return [webView _menuForElement:[self _elementAtWindowPoint:[event locationInWindow]]];
+    return [webView _menuForElement:[self _elementAtWindowPoint:[event locationInWindow]] defaultItems:nil];
 }
 
 - (NSArray *)pasteboardTypesForSelection
index 843dce5..44c9e9b 100644 (file)
@@ -55,7 +55,17 @@ enum {
     WebMenuItemTagNoGuessesFound,
     WebMenuItemTagIgnoreSpelling,
     WebMenuItemTagLearnSpelling,
-    WebMenuItemTagOther
+    WebMenuItemTagOther,
+    WebMenuItemTagOpenWithDefaultApplication,
+    WebMenuItemPDFActualSize,
+    WebMenuItemPDFZoomIn,
+    WebMenuItemPDFZoomOut,
+    WebMenuItemPDFAutoSize,
+    WebMenuItemPDFSinglePage,
+    WebMenuItemPDFFacingPages,
+    WebMenuItemPDFContinuous,
+    WebMenuItemPDFNextPage,
+    WebMenuItemPDFPreviousPage,
 };
 
 /*!
index cbf09d2..bf7f9d7 100644 (file)
@@ -622,10 +622,10 @@ static bool debugWidget = true;
     return newWindowWebView;
 }
 
-- (NSMenu *)_menuForElement:(NSDictionary *)element
+- (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items
 {
     NSArray *defaultMenuItems = [[WebDefaultUIDelegate sharedUIDelegate]
-          webView:self contextMenuItemsForElement:element defaultMenuItems:nil];
+          webView:self contextMenuItemsForElement:element defaultMenuItems:items];
     NSArray *menuItems = defaultMenuItems;
     NSMenu *menu = nil;
     unsigned i;
index a2fdddd..385988c 100644 (file)
@@ -150,7 +150,7 @@ typedef enum {
 
 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request;
 
-- (NSMenu *)_menuForElement:(NSDictionary *)element;
+- (NSMenu *)_menuForElement:(NSDictionary *)element defaultItems:(NSArray *)items;
 
 - (void)_mouseDidMoveOverElement:(NSDictionary *)dictionary modifierFlags:(unsigned)modifierFlags;