Reviewed by Adam and Darin
authorsullivan <sullivan@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 Jan 2007 21:09:40 +0000 (21:09 +0000)
committersullivan <sullivan@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 Jan 2007 21:09:40 +0000 (21:09 +0000)
        - fixed <rdar://problem/4794320> "Look Up in Dictionary" does nothing in WebKit
        (need to adopt new API)

        * Misc/WebNSURLExtras.m:
        (-[NSString _web_isUserVisibleURL]):
        random typo correction in comment

        * English.lproj/StringsNotToBeLocalized.txt:
        updated for these changes

        * WebView/WebHTMLView.mm:
        (coreGraphicsScreenPointForAppKitScreenPoint):
        new function to convert an AppKit screen point to a CG screen point
        (-[WebHTMLView _lookUpInDictionaryFromMenu:]):
        on Leopard now uses new API. There's something of an impedance mismatch between
        this API and WebKit, but that was true for the SPI we were using in Tiger also.
        Bug 4945808 covers the ways in which this is not perfect.

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

WebKit/ChangeLog
WebKit/English.lproj/StringsNotToBeLocalized.txt
WebKit/Misc/WebNSURLExtras.m
WebKit/WebView/WebHTMLView.mm

index 504bb03..5b26cc8 100644 (file)
@@ -1,3 +1,25 @@
+2007-01-22  John Sullivan  <sullivan@apple.com>
+
+        Reviewed by Adam and Darin
+
+        - fixed <rdar://problem/4794320> "Look Up in Dictionary" does nothing in WebKit 
+        (need to adopt new API)
+
+        * Misc/WebNSURLExtras.m:
+        (-[NSString _web_isUserVisibleURL]):
+        random typo correction in comment
+
+        * English.lproj/StringsNotToBeLocalized.txt:
+        updated for these changes
+
+        * WebView/WebHTMLView.mm:
+        (coreGraphicsScreenPointForAppKitScreenPoint):
+        new function to convert an AppKit screen point to a CG screen point
+        (-[WebHTMLView _lookUpInDictionaryFromMenu:]):
+        on Leopard now uses new API. There's something of an impedance mismatch between
+        this API and WebKit, but that was true for the SPI we were using in Tiger also.
+        Bug 4945808 covers the ways in which this is not perfect.
+
 2007-01-21  Darin Adler  <darin@apple.com>
 
         Reviewed by Tim H.
index ef91e4f..869cef1 100644 (file)
@@ -91,6 +91,7 @@
 "DELEGATE METHODS"
 "DOCBASE"
 "DYLD_FRAMEWORK_PATH"
+"DictionaryServices"
 "FrameName"
 "GroupName"
 "Helvetica"
 "\t"
 "\xFF\xD8\xFF\xE0"
 "_DCMDictionaryServiceWindowShow"
+"_DCSDictionaryServiceWindowShow"
 "_top"
 "a"
 "about:"
index 79a2c8c..63f4fb2 100644 (file)
@@ -749,7 +749,7 @@ typedef struct {
     int length = strlen(p);
 
     // check for characters <= 0x20 or >=0x7f, %-escape sequences of %7f, and xn--, these
-    // are the things that will lead _web_userVisisbleString to actually change things.
+    // are the things that will lead _web_userVisibleString to actually change things.
     int i;
     for (i = 0; i < length; i++) {
         unsigned char c = p[i];
index a865463..6110731 100644 (file)
@@ -5150,30 +5150,59 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 #endif /* !BUILDING_ON_TIGER */
 
+#if !BUILDING_ON_TIGER
+static CGPoint coreGraphicsScreenPointForAppKitScreenPoint(NSPoint point)
+{
+    NSRect allScreensFrame = NSZeroRect;
+    NSArray *screens = [NSScreen screens];
+    unsigned int screenCount = [screens count];
+    unsigned int screenIndex;
+    
+    // Linear search here is warranted by the fact that nobody will ever have enough screens to make this slow
+    for (screenIndex = 0; screenIndex < screenCount; screenIndex++) {
+        NSScreen *screen = [screens objectAtIndex:screenIndex];
+        NSRect screenFrame = [screen frame];
+        if (NSEqualRects(allScreensFrame, NSZeroRect))
+            allScreensFrame = screenFrame;
+        else
+            allScreensFrame = NSUnionRect(allScreensFrame, screenFrame);
+    }
+    
+    return CGPointMake(point.x, NSMaxY(allScreensFrame) - point.y);
+}
+#endif
+
 - (void)_lookUpInDictionaryFromMenu:(id)sender
 {
-    // This should only be called when there's a selection, but play it safe.
-    if (![self _hasSelection])
+    // Dictionary API will accept a whitespace-only string and display UI as if it were real text,
+    // so bail out early to avoid that.
+    if ([[[self selectedString] _webkit_stringByTrimmingWhitespace] length] == 0)
         return;
     
-    // Soft link to dictionary-display function to avoid linking another framework (ApplicationServices/LangAnalysis)
+    // We soft link to get the function that displays the dictionary (either pop-up window or app) to avoid the performance
+    // penalty of linking to another framework. This function changed signature as well as framework between Tiger and Leopard,
+    // so the two cases are handled separately.
+#if BUILDING_ON_TIGER
     static bool lookedForFunction = false;
+    
     typedef OSStatus (*ServiceWindowShowFunction)(id inWordString, NSRect inWordBoundary, UInt16 inLineDirection);
     static ServiceWindowShowFunction dictionaryServiceWindowShow;
+    
     if (!lookedForFunction) {
         const struct mach_header *frameworkImageHeader = 0;
         dictionaryServiceWindowShow = reinterpret_cast<ServiceWindowShowFunction>(
             _NSSoftLinkingGetFrameworkFuncPtr(@"ApplicationServices", @"LangAnalysis", "_DCMDictionaryServiceWindowShow", &frameworkImageHeader));
         lookedForFunction = true;
     }
+    
     if (!dictionaryServiceWindowShow) {
         LOG_ERROR("Couldn't find _DCMDictionaryServiceWindowShow"); 
         return;
     }
-
+    
     // FIXME: must check for right-to-left here
     NSWritingDirection writingDirection = NSWritingDirectionLeftToRight;
-
+    
     NSAttributedString *attrString = [self selectedAttributedString];
     // FIXME: the dictionary API expects the rect for the first line of selection. Passing
     // the rect for the entire selection, as we do here, positions the pop-up window near
@@ -5181,7 +5210,42 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
     NSRect rect = [self convertRect:core([self _frame])->visibleSelectionRect() toView:nil];
     rect.origin = [[self window] convertBaseToScreen:rect.origin];
     NSData *data = [attrString RTFFromRange:NSMakeRange(0, [attrString length]) documentAttributes:nil];
-    dictionaryServiceWindowShow(data, rect, (writingDirection == NSWritingDirectionRightToLeft) ? 1 : 0);
+    OSStatus status = dictionaryServiceWindowShow(data, rect, (writingDirection == NSWritingDirectionRightToLeft) ? 1 : 0);
+#else
+    static bool lookedForFunction = false;
+    
+    typedef void (*ServiceWindowShowFunction)(id unusedDictionaryRef, id inWordString, CFRange selectionRange, id unusedFont, CGPoint textOrigin, Boolean verticalText, id unusedTransform);
+    static ServiceWindowShowFunction dictionaryServiceWindowShow;
+    
+    if (!lookedForFunction) {
+        const struct mach_header *frameworkImageHeader = 0;
+        dictionaryServiceWindowShow = reinterpret_cast<ServiceWindowShowFunction>(
+            _NSSoftLinkingGetFrameworkFuncPtr(nil, @"DictionaryServices", "_DCSShowDictionaryServiceWindow", &frameworkImageHeader));
+        lookedForFunction = true;
+    }
+        
+    if (!dictionaryServiceWindowShow) {
+        LOG_ERROR("Couldn't find _DCSShowDictionaryServiceWindow"); 
+        return;
+    }
+    
+    // The DictionaryServices API requires the origin, in CG screen coordinates, of the first character of text in the selection.
+    // FIXME 4945808: We approximate this in a way that works well when a single word is selected, and less well in some other cases
+    // (but no worse than we did in Tiger)
+    NSAttributedString *attrString = [self selectedAttributedString];
+    NSRect rect = core([self _frame])->visibleSelectionRect();
+    
+    NSDictionary *attributes = [attrString fontAttributesInRange:NSMakeRange(0,1)];
+    NSFont *font = [attributes objectForKey:NSFontAttributeName];
+    if (font)
+        rect.origin.y += [font ascender];
+    
+    NSPoint windowPoint = [self convertPoint:rect.origin toView:nil];
+    NSPoint screenPoint = [[self window] convertBaseToScreen:windowPoint];
+    
+    dictionaryServiceWindowShow(nil, attrString, CFRangeMake(0, [attrString length]), nil, 
+                                coreGraphicsScreenPointForAppKitScreenPoint(screenPoint), false, nil);
+#endif    
 }
 
 - (void)_hoverFeedbackSuspendedChanged