Reviewed by Darin.
http://bugzilla.opendarwin.org/show_bug.cgi?id=7450
elementAtPoint is expensive and should return a smart dictionary
Support for WebKit. This removes the old elementAtPoint: on the bridge.
WebKit now uses the bridge method getInnerNonSharedNode:innerNode:URLElement:atPoint:
* WebCore.exp: removes the WebCore* dictionary keys
* bindings/objc/DOM.mm:
(-[DOMElement image]): new method to get an NSImage if the element has an image renderer
* bindings/objc/DOMHTML.mm:
(-[DOMHTMLElement titleDisplayString]): new method that returns the title after doing the backslash as currency symbol conversion
(-[DOMHTMLInputElement altDisplayString]): ditto for alt
(-[DOMHTMLImageElement altDisplayString]): ditto
(-[DOMHTMLAppletElement altDisplayString]): ditto
(-[DOMHTMLAreaElement altDisplayString]): ditto
(-[DOMHTMLAnchorElement absoluteLinkURL]): new method to get the absolute NSURL
(-[DOMHTMLAreaElement absoluteLinkURL]): ditto
(-[DOMHTMLLinkElement absoluteLinkURL]): ditto
(-[DOMHTMLInputElement absoluteImageURL]): new method to get the absolute image location as an NSURL
(-[DOMHTMLImageElement absoluteImageURL]): ditto
(-[DOMHTMLObjectElement absoluteImageURL]): ditto
* bindings/objc/DOMPrivate.h:
* bridge/mac/WebCoreFrameBridge.h:
* bridge/mac/WebCoreFrameBridge.mm:
(-[WebCoreFrameBridge getInnerNonSharedNode:innerNode:URLElement:atPoint:]):
(-[WebCoreFrameBridge isPointInsideSelection:]):
* dom/DocumentImpl.cpp:
(WebCore::DocumentImpl::prepareMouseEvent):
(WebCore::DocumentImpl::backslashAsCurrencySymbol):
* dom/DocumentImpl.h:
* rendering/render_layer.cpp:
(WebCore::RenderLayer::hitTest):
* rendering/render_object.h:
(WebCore::RenderObject::NodeInfo::URLElement):
(WebCore::RenderObject::NodeInfo::setURLElement):
WebKit:
Reviewed by Darin.
http://bugzilla.opendarwin.org/show_bug.cgi?id=7450
elementAtPoint is expensive and should return a smart dictionary
elementAtPoint for WebHTMLView now returns a WebElementDictionary,
when objectForKey is called it will lookup in the DOM, cache and return the value
* Misc/WebElementDictionary.h: Added.
* Misc/WebElementDictionary.m: Added.
(addLookupKey):
(cacheValueForKey):
(+[WebElementDictionary initializeLookupTable]):
(-[WebElementDictionary initWithInnerNonSharedNode:innerNode:URLElement:andPoint:]):
(-[WebElementDictionary dealloc]):
(-[WebElementDictionary _fillCache]):
(-[WebElementDictionary count]):
(-[WebElementDictionary keyEnumerator]):
(-[WebElementDictionary objectForKey:]):
(-[WebElementDictionary _domNode]):
(-[WebElementDictionary _webFrame]):
(-[WebElementDictionary _targetWebFrame]):
(-[WebElementDictionary _title]):
(-[WebElementDictionary _imageRect]):
(-[WebElementDictionary _isSelected]):
* Misc/WebNSViewExtras.m:
(-[NSView _web_dragImage:element:rect:event:pasteboard:source:offset:]):
* WebKit.xcodeproj/project.pbxproj:
* WebView/WebHTMLView.m:
(-[WebHTMLView _updateMouseoverWithEvent:]):
(-[WebHTMLView _startDraggingImage:at:operation:event:sourceIsDHTML:DHTMLWroteData:]):
(-[NSArray elementAtPoint:]):
* WebView/WebView.m:
* WebView/WebViewPrivate.h:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@13070
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2006-03-01 Timothy Hatcher <timothy@apple.com>
+
+ Reviewed by Darin.
+
+ http://bugzilla.opendarwin.org/show_bug.cgi?id=7450
+ elementAtPoint is expensive and should return a smart dictionary
+
+ Support for WebKit. This removes the old elementAtPoint: on the bridge.
+ WebKit now uses the bridge method getInnerNonSharedNode:innerNode:URLElement:atPoint:
+
+ * WebCore.exp: removes the WebCore* dictionary keys
+ * bindings/objc/DOM.mm:
+ (-[DOMElement image]): new method to get an NSImage if the element has an image renderer
+ * bindings/objc/DOMHTML.mm:
+ (-[DOMHTMLElement titleDisplayString]): new method that returns the title after doing the backslash as currency symbol conversion
+ (-[DOMHTMLInputElement altDisplayString]): ditto for alt
+ (-[DOMHTMLImageElement altDisplayString]): ditto
+ (-[DOMHTMLAppletElement altDisplayString]): ditto
+ (-[DOMHTMLAreaElement altDisplayString]): ditto
+ (-[DOMHTMLAnchorElement absoluteLinkURL]): new method to get the absolute NSURL
+ (-[DOMHTMLAreaElement absoluteLinkURL]): ditto
+ (-[DOMHTMLLinkElement absoluteLinkURL]): ditto
+ (-[DOMHTMLInputElement absoluteImageURL]): new method to get the absolute image location as an NSURL
+ (-[DOMHTMLImageElement absoluteImageURL]): ditto
+ (-[DOMHTMLObjectElement absoluteImageURL]): ditto
+ * bindings/objc/DOMPrivate.h:
+ * bridge/mac/WebCoreFrameBridge.h:
+ * bridge/mac/WebCoreFrameBridge.mm:
+ (-[WebCoreFrameBridge getInnerNonSharedNode:innerNode:URLElement:atPoint:]):
+ (-[WebCoreFrameBridge isPointInsideSelection:]):
+ * dom/DocumentImpl.cpp:
+ (WebCore::DocumentImpl::prepareMouseEvent):
+ (WebCore::DocumentImpl::backslashAsCurrencySymbol):
+ * dom/DocumentImpl.h:
+ * rendering/render_layer.cpp:
+ (WebCore::RenderLayer::hitTest):
+ * rendering/render_object.h:
+ (WebCore::RenderObject::NodeInfo::URLElement):
+ (WebCore::RenderObject::NodeInfo::setURLElement):
+
2006-03-01 Mitz Pettel <opendarwin.org@mitzpettel.com>
Test: fast/css/hover-subselector.html
.objc_class_name_WebCoreTextRendererFactory
.objc_class_name_WebCoreViewFactory
.objc_class_name_WebDashboardRegion
-_WebCoreElementDOMNodeKey
-_WebCoreElementFrameKey
-_WebCoreElementImageAltStringKey
-_WebCoreElementImageRectKey
-_WebCoreElementImageURLKey
-_WebCoreElementIsSelectedKey
-_WebCoreElementLinkLabelKey
-_WebCoreElementLinkTargetFrameKey
-_WebCoreElementLinkTitleKey
-_WebCoreElementLinkURLKey
-_WebCoreElementTitleKey
_WebCoreInitializeEmptyTextGeometry
_WebCoreInitializeEmptyTextStyle
_WebCoreInitializeFont
@implementation DOMElement (DOMElementExtensions)
+- (NSImage*)image
+{
+ RenderObject* renderer = [self _elementImpl]->renderer();
+ if (renderer && renderer->isImage()) {
+ RenderImage* img = static_cast<RenderImage*>(renderer);
+ if (img->cachedImage() && !img->cachedImage()->isErrorImage())
+ return img->cachedImage()->image()->getNSImage();
+ }
+ return nil;
+}
+
- (void)focus
{
[self _elementImpl]->focus();
return nil;
}
-- (NSImage*)_image
-{
- RenderObject *renderer = [self _elementImpl]->renderer();
- if (renderer && renderer->isImage()) {
- RenderImage* img = static_cast<RenderImage*>(renderer);
- if (img->cachedImage() && !img->cachedImage()->isErrorImage())
- return img->cachedImage()->image()->getNSImage();
- }
- return nil;
-}
-
- (NSData*)_imageTIFFRepresentation
{
RenderObject *renderer = [self _elementImpl]->renderer();
#import "DOMExtensions.h"
#import "DOMInternal.h"
+#import "DOMPrivate.h"
#import "DOMHTMLInternal.h"
#import <kxmlcore/Assertions.h>
#import "FoundationExtras.h"
return [self _HTMLElementImpl]->title();
}
+- (NSString *)titleDisplayString
+{
+ return [self _HTMLElementImpl]->title().replace('\\', [self _elementImpl]->getDocument()->backslashAsCurrencySymbol());
+}
+
- (void)setTitle:(NSString *)title
{
[self _HTMLElementImpl]->setTitle(title);
[self _linkElementImpl]->setCharset(charset);
}
+- (NSURL *)absoluteLinkURL
+{
+ return [self _getURLAttribute:@"href"];
+}
+
- (NSString *)href
{
return [self _linkElementImpl]->href();
return [self _inputElementImpl]->alt();
}
+- (NSString *)altDisplayString
+{
+ return [self _inputElementImpl]->alt().replace('\\', [self _elementImpl]->getDocument()->backslashAsCurrencySymbol());
+}
+
- (void)setAlt:(NSString *)alt
{
[self _inputElementImpl]->setAlt(alt);
[self _inputElementImpl]->setSize(size);
}
+- (NSURL *)absoluteImageURL
+{
+ if (![self _inputElementImpl]->renderer() || ![self _inputElementImpl]->renderer()->isImage())
+ return nil;
+ return [self _getURLAttribute:@"src"];
+}
+
- (NSString *)src
{
return [self _inputElementImpl]->src();
[self _anchorElementImpl]->setAttribute(coordsAttr, coords);
}
+- (NSURL *)absoluteLinkURL
+{
+ return [self _getURLAttribute:@"href"];
+}
+
- (NSString *)href
{
return [self _anchorElementImpl]->href();
return [self _imageElementImpl]->getAttribute(altAttr);
}
+- (NSString *)altDisplayString
+{
+ String alt = [self _imageElementImpl]->getAttribute(altAttr);
+ return alt.replace('\\', [self _elementImpl]->getDocument()->backslashAsCurrencySymbol());
+}
+
- (void)setAlt:(NSString *)alt
{
[self _imageElementImpl]->setAttribute(altAttr, alt);
[self _imageElementImpl]->setAttribute(longdescAttr, longDesc);
}
+- (NSURL *)absoluteImageURL
+{
+ return [self _getURLAttribute:@"src"];
+}
+
- (NSString *)src
{
return [self _imageElementImpl]->src();
[self _objectElementImpl]->setAttribute(codetypeAttr, codeType);
}
+- (NSURL *)absoluteImageURL
+{
+ if (![self _objectElementImpl]->renderer() || ![self _objectElementImpl]->renderer()->isImage())
+ return nil;
+ return [self _getURLAttribute:@"data"];
+}
+
- (NSString *)data
{
return [self _objectElementImpl]->getAttribute(dataAttr);
return [self _appletElementImpl]->getAttribute(altAttr);
}
+- (NSString *)altDisplayString
+{
+ String alt = [self _appletElementImpl]->getAttribute(altAttr);
+ return alt.replace('\\', [self _elementImpl]->getDocument()->backslashAsCurrencySymbol());
+}
+
- (void)setAlt:(NSString *)alt
{
[self _appletElementImpl]->setAttribute(altAttr, alt);
return [self _areaElementImpl]->getAttribute(altAttr);
}
+- (NSString *)altDisplayString
+{
+ String alt = [self _areaElementImpl]->getAttribute(altAttr);
+ return alt.replace('\\', [self _elementImpl]->getDocument()->backslashAsCurrencySymbol());
+}
+
- (void)setAlt:(NSString *)alt
{
[self _areaElementImpl]->setAttribute(altAttr, alt);
[self _areaElementImpl]->setAttribute(coordsAttr, coords);
}
+- (NSURL *)absoluteLinkURL
+{
+ return [self _getURLAttribute:@"href"];
+}
+
- (NSString *)href
{
return [self _areaElementImpl]->href();
@interface DOMElement (WebPrivate)
- (NSFont *)_font;
-- (NSImage *)_image;
- (NSData *)_imageTIFFRepresentation;
- (NSURL *)_getURLAttribute:(NSString *)name;
@end
- (void)_activateItemAtIndex:(int)index;
@end
-// BEGIN PENDING PUBLIC WEB INSPECTOR APIS
-// These APIs are for the Web Inspector, and they will be made public eventually.
+// BEGIN PENDING PUBLIC APIS
+// These APIs will be made public eventually.
@interface DOMAttr (DOMAttrExtensions)
- (DOMCSSStyleDeclaration *)style;
@end
@end
@interface DOMElement (DOMElementExtensions)
+- (NSImage *)image;
- (void)focus;
- (void)blur;
- (void)scrollIntoView:(BOOL)alignTop;
- (void)scrollIntoViewIfNeeded:(BOOL)centerIfNeeded;
@end
+
+@interface DOMHTMLElement (DOMHTMLElementPendingPublic)
+- (NSString *)titleDisplayString;
+@end
+
+@interface DOMHTMLInputElement (DOMHTMLInputElementPendingPublic)
+- (NSString *)altDisplayString;
+- (NSURL *)absoluteImageURL;
+@end
+
+@interface DOMHTMLImageElement (DOMHTMLImageElementPendingPublic)
+- (NSString *)altDisplayString;
+- (NSURL *)absoluteImageURL;
+@end
+
+@interface DOMHTMLObjectElement (DOMHTMLObjectElementPendingPublic)
+- (NSURL *)absoluteImageURL;
+@end
+
+@interface DOMHTMLAnchorElement (DOMHTMLAnchorElementPendingPublic)
+- (NSURL *)absoluteLinkURL;
+@end
+
+@interface DOMHTMLAreaElement (DOMHTMLAreaElementPendingPublic)
+- (NSURL *)absoluteLinkURL;
+@end
+
+@interface DOMHTMLLinkElement (DOMHTMLLinkElementPendingPublic)
+- (NSURL *)absoluteLinkURL;
+@end
+
// END
// Pending DOM3 APIs
@protocol WebCoreFileButton;
@protocol WebCoreFileButtonDelegate;
-extern NSString *WebCoreElementDOMNodeKey;
-extern NSString *WebCoreElementFrameKey;
-extern NSString *WebCoreElementImageAltStringKey;
-extern NSString *WebCoreElementImageRectKey;
-extern NSString *WebCoreElementImageURLKey;
-extern NSString *WebCoreElementIsSelectedKey;
-extern NSString *WebCoreElementLinkURLKey;
-extern NSString *WebCoreElementLinkTargetFrameKey;
-extern NSString *WebCoreElementLinkLabelKey;
-extern NSString *WebCoreElementLinkTitleKey;
-extern NSString *WebCoreElementTitleKey;
-
extern NSString *WebCorePageCacheStateKey;
typedef enum {
- (NSObject *)copyRenderTree:(id <WebCoreRenderTreeCopier>)copier;
- (NSString *)renderTreeAsExternalRepresentation;
-- (NSDictionary *)elementAtPoint:(NSPoint)point;
+- (void)getInnerNonSharedNode:(DOMNode **)innerNonSharedNode innerNode:(DOMNode **)innerNode URLElement:(DOMElement **)URLElement atPoint:(NSPoint)point;
+- (BOOL)isPointInsideSelection:(NSPoint)point;
+
- (NSURL *)URLWithAttributeString:(NSString *)string;
- (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form;
using WebCore::RenderObject;
-NSString *WebCoreElementDOMNodeKey = @"WebElementDOMNode";
-NSString *WebCoreElementFrameKey = @"WebElementFrame";
-NSString *WebCoreElementImageAltStringKey = @"WebElementImageAltString";
-NSString *WebCoreElementImageRectKey = @"WebElementImageRect";
-NSString *WebCoreElementImageURLKey = @"WebElementImageURL";
-NSString *WebCoreElementIsSelectedKey = @"WebElementIsSelected";
-NSString *WebCoreElementLinkURLKey = @"WebElementLinkURL";
-NSString *WebCoreElementLinkTargetFrameKey = @"WebElementTargetFrame";
-NSString *WebCoreElementLinkLabelKey = @"WebElementLinkLabel";
-NSString *WebCoreElementLinkTitleKey = @"WebElementLinkTitle";
-NSString *WebCoreElementNameKey = @"WebElementName";
-NSString *WebCoreElementTitleKey = @"WebCoreElementTitle"; // not in WebKit API for now, could be in API some day
-
NSString *WebCorePageCacheStateKey = @"WebCorePageCacheState";
@interface WebCoreFrameBridge (WebCoreBridgeInternal)
return m_frame->matchLabelsAgainstElement(labels, [element _elementImpl]);
}
-- (NSDictionary *)elementAtPoint:(NSPoint)point
+- (void)getInnerNonSharedNode:(DOMNode **)innerNonSharedNode innerNode:(DOMNode **)innerNode URLElement:(DOMElement **)URLElement atPoint:(NSPoint)point
{
RenderObject *renderer = m_frame->renderer();
- if (!renderer)
- return nil;
-
- RenderObject::NodeInfo nodeInfo = [self nodeInfoAtPoint:point];
-
- NSMutableDictionary *element = [NSMutableDictionary dictionary];
- [element setObject:[NSNumber numberWithBool:m_frame->isPointInsideSelection((int)point.x, (int)point.y)]
- forKey:WebCoreElementIsSelectedKey];
-
- // Find the title in the nearest enclosing DOM node.
- // For <area> tags in image maps, walk the tree for the <area>, not the <img> using it.
- for (NodeImpl *titleNode = nodeInfo.innerNode(); titleNode; titleNode = titleNode->parentNode()) {
- if (titleNode->isElementNode()) {
- const AtomicString& title = static_cast<ElementImpl *>(titleNode)->getAttribute(titleAttr);
- if (!title.isNull()) {
- // We found a node with a title.
- QString titleText = title.qstring();
- titleText.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
- [element setObject:titleText.getNSString() forKey:WebCoreElementTitleKey];
- break;
- }
- }
- }
-
- NodeImpl *URLNode = nodeInfo.URLElement();
- if (URLNode) {
- ElementImpl *e = static_cast<ElementImpl *>(URLNode);
- DocumentImpl *doc = e->getDocument();
- ASSERT(doc);
-
- const AtomicString& title = e->getAttribute(titleAttr);
- if (!title.isEmpty()) {
- QString titleText = title.qstring();
- titleText.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
- [element setObject:titleText.getNSString() forKey:WebCoreElementLinkTitleKey];
- }
-
- const AtomicString& link = e->getAttribute(hrefAttr);
- if (!link.isNull()) {
- QString t = plainText(rangeOfContents(e).get());
- if (!t.isEmpty()) {
- [element setObject:t.getNSString() forKey:WebCoreElementLinkLabelKey];
- }
- QString URLString = parseURL(link).qstring();
- [element setObject:doc->completeURL(URLString).getNSString() forKey:WebCoreElementLinkURLKey];
- }
-
- DOMString target = e->getAttribute(targetAttr);
- if (target.isEmpty() && doc) { // FIXME: Take out this doc check when we're not just before a release.
- target = doc->baseTarget();
- }
- if (!target.isEmpty()) {
- [element setObject:target.qstring().getNSString() forKey:WebCoreElementLinkTargetFrameKey];
- }
+ if (!renderer) {
+ *innerNonSharedNode = nil;
+ *innerNode = nil;
+ *URLElement = nil;
+ return;
}
- NodeImpl *node = nodeInfo.innerNonSharedNode();
- if (node) {
- [element setObject:[DOMNode _nodeWithImpl:node] forKey:WebCoreElementDOMNodeKey];
-
- // Only return image information if there is an image.
- if (node->renderer() && node->renderer()->isImage()) {
- RenderImage *r = static_cast<RenderImage *>(node->renderer());
- int x, y;
- if (r->absolutePosition(x, y)) {
- NSValue *rect = [NSValue valueWithRect:NSMakeRect(x, y, r->contentWidth(), r->contentHeight())];
- [element setObject:rect forKey:WebCoreElementImageRectKey];
- }
+ RenderObject::NodeInfo nodeInfo = [self nodeInfoAtPoint:point];
+ *innerNonSharedNode = [DOMNode _nodeWithImpl:nodeInfo.innerNonSharedNode()];
+ *innerNode = [DOMNode _nodeWithImpl:nodeInfo.innerNode()];
+ *URLElement = [DOMElement _elementWithImpl:nodeInfo.URLElement()];
+}
- ElementImpl *i = static_cast<ElementImpl*>(node);
-
- // FIXME: Code copied from RenderImage::updateFromElement; should share.
- DOMString attr;
- if (i->hasTagName(objectTag)) {
- attr = i->getAttribute(dataAttr);
- } else {
- attr = i->getAttribute(srcAttr);
- }
- if (!attr.isEmpty()) {
- QString URLString = parseURL(attr).qstring();
- [element setObject:i->getDocument()->completeURL(URLString).getNSString() forKey:WebCoreElementImageURLKey];
- }
-
- // FIXME: Code copied from RenderImage::updateFromElement; should share.
- DOMString alt;
- if (i->hasTagName(inputTag))
- alt = static_cast<HTMLInputElementImpl *>(i)->altText();
- else if (i->hasTagName(imgTag))
- alt = static_cast<HTMLImageElementImpl *>(i)->altText();
- if (!alt.isNull()) {
- QString altText = alt.qstring();
- altText.replace(QChar('\\'), m_frame->backslashAsCurrencySymbol());
- [element setObject:altText.getNSString() forKey:WebCoreElementImageAltStringKey];
- }
- }
- }
-
- return element;
+- (BOOL)isPointInsideSelection:(NSPoint)point
+{
+ return m_frame->isPointInsideSelection((int)point.x, (int)point.y);
}
- (NSURL *)URLWithAttributeString:(NSString *)string
#include "CDATASectionImpl.h"
#include "CommentImpl.h"
+#include "decoder.h"
#include "DOMImplementationImpl.h"
#include "DocLoader.h"
#include "DocumentFragmentImpl.h"
String href;
String target;
if (renderInfo.URLElement()) {
- assert(renderInfo.URLElement()->isElementNode());
- ElementImpl* e = static_cast<ElementImpl*>(renderInfo.URLElement());
+ ElementImpl* e = renderInfo.URLElement();
href = parseURL(e->getAttribute(hrefAttr));
if (!href.isNull())
target = e->getAttribute(targetAttr);
m_decoder = decoder;
}
+QChar DocumentImpl::backslashAsCurrencySymbol() const
+{
+ if (!m_decoder)
+ return '\\';
+ return m_decoder->encoding().backslashAsCurrencySymbol();
+}
+
QString DocumentImpl::completeURL(const QString &URL)
{
if (!m_decoder)
void setDecoder(Decoder*);
Decoder* decoder() const { return m_decoder.get(); }
+ QChar backslashAsCurrencySymbol() const;
+
#if __APPLE__
void setDashboardRegionsDirty(bool f) { m_dashboardRegionsDirty = f; }
bool dashboardRegionsDirty() const { return m_dashboardRegionsDirty; }
NodeImpl* node = info.innerNode();
while (node) {
if (node->isLink() && !info.URLElement())
- info.setURLElement(node);
+ info.setURLElement(static_cast<ElementImpl*>(node));
node = node->parentNode();
}
NodeImpl* innerNode() const { return m_innerNode; }
NodeImpl* innerNonSharedNode() const { return m_innerNonSharedNode; }
- NodeImpl* URLElement() const { return m_innerURLElement; }
+ ElementImpl* URLElement() const { return m_innerURLElement; }
bool readonly() const { return m_readonly; }
bool active() const { return m_active; }
bool mouseMove() const { return m_mouseMove; }
void setInnerNode(NodeImpl* n) { m_innerNode = n; }
void setInnerNonSharedNode(NodeImpl* n) { m_innerNonSharedNode = n; }
- void setURLElement(NodeImpl* n) { m_innerURLElement = n; }
+ void setURLElement(ElementImpl* n) { m_innerURLElement = n; }
private:
NodeImpl* m_innerNode;
NodeImpl* m_innerNonSharedNode;
- NodeImpl* m_innerURLElement;
+ ElementImpl* m_innerURLElement;
bool m_readonly;
bool m_active;
bool m_mouseMove;
+2006-03-01 Timothy Hatcher <timothy@apple.com>
+
+ Reviewed by Darin.
+
+ http://bugzilla.opendarwin.org/show_bug.cgi?id=7450
+ elementAtPoint is expensive and should return a smart dictionary
+
+ elementAtPoint for WebHTMLView now returns a WebElementDictionary,
+ when objectForKey is called it will lookup in the DOM, cache and return the value
+
+ * Misc/WebElementDictionary.h: Added.
+ * Misc/WebElementDictionary.m: Added.
+ (addLookupKey):
+ (cacheValueForKey):
+ (+[WebElementDictionary initializeLookupTable]):
+ (-[WebElementDictionary initWithInnerNonSharedNode:innerNode:URLElement:andPoint:]):
+ (-[WebElementDictionary dealloc]):
+ (-[WebElementDictionary _fillCache]):
+ (-[WebElementDictionary count]):
+ (-[WebElementDictionary keyEnumerator]):
+ (-[WebElementDictionary objectForKey:]):
+ (-[WebElementDictionary _domNode]):
+ (-[WebElementDictionary _webFrame]):
+ (-[WebElementDictionary _targetWebFrame]):
+ (-[WebElementDictionary _title]):
+ (-[WebElementDictionary _imageRect]):
+ (-[WebElementDictionary _isSelected]):
+ * Misc/WebNSViewExtras.m:
+ (-[NSView _web_dragImage:element:rect:event:pasteboard:source:offset:]):
+ * WebKit.xcodeproj/project.pbxproj:
+ * WebView/WebHTMLView.m:
+ (-[WebHTMLView _updateMouseoverWithEvent:]):
+ (-[WebHTMLView _startDraggingImage:at:operation:event:sourceIsDHTML:DHTMLWroteData:]):
+ (-[NSArray elementAtPoint:]):
+ * WebView/WebView.m:
+ * WebView/WebViewPrivate.h:
+
2006-02-28 Darin Adler <darin@apple.com>
Reviewed by Adele.
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, 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 <Foundation/NSDictionary.h>
+
+@class DOMNode;
+@class DOMElement;
+
+@interface WebElementDictionary : NSDictionary {
+ DOMNode *_innerNode;
+ DOMNode *_innerNonSharedNode;
+ DOMElement *_URLElement;
+ NSMutableDictionary *_cache;
+ NSMutableSet *_nilValues;
+ NSPoint _point;
+ BOOL _cacheComplete;
+}
+- (id)initWithInnerNonSharedNode:(DOMNode *)innerNonSharedNode innerNode:(DOMNode *)innerNode URLElement:(DOMElement *)URLElement andPoint:(NSPoint)point;
+@end
--- /dev/null
+/*
+ * Copyright (C) 2006 Apple Computer, 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 "WebElementDictionary.h"
+
+#import "WebDOMOperations.h"
+#import "WebFrame.h"
+#import "WebFrameBridge.h"
+#import "WebView.h"
+#import "WebViewPrivate.h"
+
+#import <WebKit/DOMCore.h>
+#import <WebKit/DOMPrivate.h>
+
+typedef enum {
+ WebElementSelf,
+ WebElementInnerNode,
+ WebElementInnerNonSharedNode,
+ WebElementURLElement
+} WebElementTargetObject;
+
+typedef struct WebElementMethod {
+ WebElementTargetObject target;
+ SEL selector;
+} WebElementMethod;
+
+static CFMutableDictionaryRef lookupTable = NULL;
+
+static void addLookupKey(NSString *key, SEL selector, WebElementTargetObject target)
+{
+ WebElementMethod *elementMethod = malloc(sizeof(WebElementMethod));
+ elementMethod->target = target;
+ elementMethod->selector = selector;
+ CFDictionaryAddValue(lookupTable, key, elementMethod);
+}
+
+static void cacheValueForKey(const void *key, const void *value, void *self)
+{
+ // calling objectForKey will cache the value in our _cache dictionary
+ [(WebElementDictionary *)self objectForKey:(NSString *)key];
+}
+
+@implementation WebElementDictionary
++ (void)initializeLookupTable
+{
+ if (lookupTable)
+ return;
+
+ lookupTable = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, NULL);
+
+ addLookupKey(WebElementDOMNodeKey, @selector(_domNode), WebElementSelf);
+ addLookupKey(WebElementFrameKey, @selector(_webFrame), WebElementSelf);
+ addLookupKey(WebElementImageAltStringKey, @selector(altDisplayString), WebElementInnerNonSharedNode);
+ addLookupKey(WebElementImageKey, @selector(image), WebElementInnerNonSharedNode);
+ addLookupKey(WebElementImageRectKey, @selector(_imageRect), WebElementSelf);
+ addLookupKey(WebElementImageURLKey, @selector(absoluteImageURL), WebElementInnerNonSharedNode);
+ addLookupKey(WebElementIsSelectedKey, @selector(_isSelected), WebElementSelf);
+ addLookupKey(WebElementTitleKey, @selector(_title), WebElementSelf);
+ addLookupKey(WebElementLinkURLKey, @selector(absoluteLinkURL), WebElementURLElement);
+ addLookupKey(WebElementLinkTargetFrameKey, @selector(_targetWebFrame), WebElementSelf);
+ addLookupKey(WebElementLinkTitleKey, @selector(titleDisplayString), WebElementURLElement);
+ addLookupKey(WebElementLinkLabelKey, @selector(textContent), WebElementURLElement);
+}
+
+- (id)initWithInnerNonSharedNode:(DOMNode *)innerNonSharedNode innerNode:(DOMNode *)innerNode URLElement:(DOMElement *)URLElement andPoint:(NSPoint)point
+{
+ [[self class] initializeLookupTable];
+ [super init];
+ _point = point;
+ _innerNode = [innerNode retain];
+ _innerNonSharedNode = [innerNonSharedNode retain];
+ _URLElement = [URLElement retain];
+ return self;
+}
+
+- (void)dealloc
+{
+ [_innerNode release];
+ [_innerNonSharedNode release];
+ [_URLElement release];
+ [_cache release];
+ [_nilValues release];
+ [super dealloc];
+}
+
+- (void)_fillCache
+{
+ CFDictionaryApplyFunction(lookupTable, cacheValueForKey, self);
+ _cacheComplete = YES;
+}
+
+- (unsigned)count
+{
+ if (!_cacheComplete)
+ [self _fillCache];
+ return [_cache count];
+}
+
+- (NSEnumerator *)keyEnumerator
+{
+ if (!_cacheComplete)
+ [self _fillCache];
+ return [_cache keyEnumerator];
+}
+
+- (id)objectForKey:(id)key
+{
+ id value = [_cache objectForKey:key];
+ if (value || _cacheComplete || [_nilValues containsObject:key])
+ return value;
+
+ WebElementMethod *elementMethod = (WebElementMethod *)CFDictionaryGetValue(lookupTable, key);
+ if (!elementMethod)
+ return nil;
+
+ id target = nil;
+ switch (elementMethod->target) {
+ case WebElementSelf:
+ target = self;
+ break;
+ case WebElementInnerNonSharedNode:
+ target = _innerNonSharedNode;
+ break;
+ case WebElementInnerNode:
+ target = _innerNode;
+ break;
+ case WebElementURLElement:
+ target = _URLElement;
+ break;
+ }
+
+ if (target && [target respondsToSelector:elementMethod->selector])
+ value = [target performSelector:elementMethod->selector];
+
+ unsigned lookupTableCount = CFDictionaryGetCount(lookupTable);
+
+ if (value) {
+ if (!_cache)
+ _cache = [[NSMutableDictionary alloc] initWithCapacity:lookupTableCount];
+ [_cache setObject:value forKey:key];
+ } else {
+ if (!_nilValues)
+ _nilValues = [[NSMutableSet alloc] initWithCapacity:lookupTableCount];
+ [_nilValues addObject:key];
+ }
+
+ _cacheComplete = ([_cache count] + [_nilValues count]) == lookupTableCount;
+
+ return value;
+}
+
+- (DOMNode *)_domNode
+{
+ return [[_innerNonSharedNode retain] autorelease];
+}
+
+- (WebFrame *)_webFrame
+{
+ return [[_innerNonSharedNode ownerDocument] webFrame];
+}
+
+- (WebFrame *)_targetWebFrame
+{
+ if (!_URLElement || ![_URLElement respondsToSelector:@selector(target)])
+ return nil;
+ WebFrame *webFrame = [[_innerNonSharedNode ownerDocument] webFrame];
+ NSString *targetName = [_URLElement performSelector:@selector(target)];
+ if ([targetName length])
+ return [webFrame findFrameNamed:targetName];
+ return webFrame;
+}
+
+- (NSString *)_title
+{
+ // Find the title in the nearest enclosing DOM node.
+ // For <area> tags in image maps, walk the tree for the <area>, not the <img> using it.
+ for (DOMNode *titleNode = _innerNode; titleNode; titleNode = [titleNode parentNode]) {
+ if ([titleNode isKindOfClass:[DOMHTMLElement class]]) {
+ NSString *title = [(DOMHTMLElement *)titleNode titleDisplayString];
+ if ([title length])
+ return title;
+ }
+ }
+ return nil;
+}
+
+- (NSValue *)_imageRect
+{
+ if ([self objectForKey:WebElementImageURLKey])
+ return [NSValue valueWithRect:[_innerNonSharedNode boundingBox]];
+ return nil;
+}
+
+- (NSNumber *)_isSelected
+{
+ return [NSNumber numberWithBool:[[[[_innerNonSharedNode ownerDocument] webFrame] _bridge] isPointInsideSelection:_point]];
+}
+@end
NSImage *dragImage;
NSPoint origin;
- NSImage *image = (wir != nil) ? [wir image] : [element _image];
+ NSImage *image = (wir != nil) ? [wir image] : [element image];
if (image != nil && [image size].height * [image size].width <= WebMaxOriginalImageArea) {
NSSize originalSize = rect.size;
origin = rect.origin;
9398112E0824BF01008DF038 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D623DD051E791F002F47DD /* libicucore.dylib */; };
9398112F0824BF01008DF038 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 830E81E005853AC000AD0891 /* Security.framework */; };
ABDDF20D08EB0DDC001E1241 /* WebDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = ABDDF20C08EB0DDC001E1241 /* WebDownloadInternal.h */; };
+ DD89682009AA87240097E7F0 /* WebElementDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = DD89681E09AA87240097E7F0 /* WebElementDictionary.h */; };
+ DD89682109AA87240097E7F0 /* WebElementDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = DD89681F09AA87240097E7F0 /* WebElementDictionary.m */; };
ED6BE2E7088C32B50044DEDC /* WebNSAttributedStringExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = ED6BE2E5088C32B50044DEDC /* WebNSAttributedStringExtras.h */; };
ED6BE2E8088C32B50044DEDC /* WebNSAttributedStringExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = ED6BE2E6088C32B50044DEDC /* WebNSAttributedStringExtras.m */; };
ED7F6D8B0980683500C235ED /* WebNSDataExtrasPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = ED7F6D8A0980683500C235ED /* WebNSDataExtrasPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
BEE18F9A0472B73200CA289C /* WebLocalizableStrings.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebLocalizableStrings.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
BEE52D4A0473032500CA289C /* WebKitSystemBits.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebKitSystemBits.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
BEE52D4B0473032500CA289C /* WebKitSystemBits.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebKitSystemBits.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
+ DD89681E09AA87240097E7F0 /* WebElementDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebElementDictionary.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
+ DD89681F09AA87240097E7F0 /* WebElementDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebElementDictionary.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
ED21B9810528F7AA003299AC /* WebDocumentInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebDocumentInternal.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
ED2B2474033A2DA800C1A526 /* WebNSPasteboardExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebNSPasteboardExtras.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
ED2B2475033A2DA800C1A526 /* WebNSPasteboardExtras.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebNSPasteboardExtras.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
F59668C902AD2923018635CA /* WebStringTruncator.m */,
6578F5DE045F817400000128 /* WebDownload.h */,
6578F5DF045F817400000128 /* WebDownload.m */,
+ DD89681E09AA87240097E7F0 /* WebElementDictionary.h */,
+ DD89681F09AA87240097E7F0 /* WebElementDictionary.m */,
);
path = Misc;
sourceTree = "<group>";
ED7F6D8B0980683500C235ED /* WebNSDataExtrasPrivate.h in Headers */,
651951E209974178003DFC65 /* WebLoader.h in Headers */,
6550B7C7099EFAE90090D781 /* WebArchiver.h in Headers */,
+ DD89682009AA87240097E7F0 /* WebElementDictionary.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
1C68F672095B5FC100C2984E /* WebNodeHighlightView.m in Sources */,
65C7F42D0979DE640022E453 /* WebPageBridge.m in Sources */,
6550B7C8099EFAE90090D781 /* WebArchiver.m in Sources */,
+ DD89682109AA87240097E7F0 /* WebElementDictionary.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
#import <WebKit/WebDocumentInternal.h>
#import <WebKit/WebDOMOperationsPrivate.h>
#import <WebKit/WebEditingDelegate.h>
+#import <WebKit/WebElementDictionary.h>
#import <WebKit/WebFramePrivate.h>
#import <WebKit/WebFrameInternal.h>
#import <WebKit/WebFrameViewInternal.h>
newToolTip = [[(DOMHTMLInputElement *) domElement form] action];
}
if (newToolTip == nil)
- newToolTip = [[element objectForKey:WebCoreElementLinkURLKey] _web_userVisibleString];
+ newToolTip = [[element objectForKey:WebElementLinkURLKey] _web_userVisibleString];
}
if (newToolTip == nil)
- newToolTip = [element objectForKey:WebCoreElementTitleKey];
+ newToolTip = [element objectForKey:WebElementTitleKey];
[view _setToolTip:newToolTip];
[view release];
// note per kwebster, the offset arg below is always ignored in positioning the image
DOMHTMLElement *imageElement = [element objectForKey:WebElementDOMNodeKey];
- if (imageURL != nil && [imageElement _image] != nil && (_private->dragSourceActionMask & WebDragSourceActionImage)) {
+ if (imageURL != nil && [imageElement image] != nil && (_private->dragSourceActionMask & WebDragSourceActionImage)) {
id source = self;
if (!dhtmlWroteData) {
// Select the image when it is dragged. This allows the image to be moved via MoveSelectionCommandImpl and this matches NSTextView's behavior.
- (NSDictionary *)elementAtPoint:(NSPoint)point
{
- NSDictionary *elementInfoWC = [[self _bridge] elementAtPoint:point];
- NSMutableDictionary *elementInfo = [elementInfoWC mutableCopy];
-
- // Convert URL strings to NSURLs.
- [elementInfo _web_setObjectIfNotNil:[NSURL _web_URLWithDataAsString:[elementInfoWC objectForKey:WebElementLinkURLKey]] forKey:WebElementLinkURLKey];
- [elementInfo _web_setObjectIfNotNil:[NSURL _web_URLWithDataAsString:[elementInfoWC objectForKey:WebElementImageURLKey]] forKey:WebElementImageURLKey];
- if ([elementInfoWC objectForKey:WebElementImageURLKey])
- [elementInfo _web_setObjectIfNotNil:[[elementInfoWC objectForKey:WebElementDOMNodeKey] _image] forKey:WebElementImageKey];
-
- WebFrameView *webFrameView = [self _web_parentWebFrameView];
- ASSERT(webFrameView);
- WebFrame *webFrame = [webFrameView webFrame];
-
- if (webFrame) {
- NSString *frameName = [elementInfoWC objectForKey:WebElementLinkTargetFrameKey];
- if ([frameName length] == 0) {
- [elementInfo setObject:webFrame forKey:WebElementLinkTargetFrameKey];
- } else {
- WebFrame *wf = [webFrame findFrameNamed:frameName];
- if (wf != nil)
- [elementInfo setObject:wf forKey:WebElementLinkTargetFrameKey];
- else
- [elementInfo removeObjectForKey:WebElementLinkTargetFrameKey];
- }
-
- [elementInfo setObject:webFrame forKey:WebElementFrameKey];
- }
-
- return [elementInfo autorelease];
+ DOMNode *innerNode = nil;
+ DOMNode *innerNonSharedNode = nil;
+ DOMElement *URLElement = nil;
+ [[self _bridge] getInnerNonSharedNode:&innerNonSharedNode innerNode:&innerNode URLElement:&URLElement atPoint:point];
+ return [[[WebElementDictionary alloc] initWithInnerNonSharedNode:innerNonSharedNode innerNode:innerNode URLElement:URLElement andPoint:point] autorelease];
}
- (void)mouseUp:(NSEvent *)event
NSString *WebElementImageRectKey = @"WebElementImageRect";
NSString *WebElementImageURLKey = @"WebElementImageURL";
NSString *WebElementIsSelectedKey = @"WebElementIsSelected";
+NSString *WebElementTitleKey = @"WebElementTitle";
NSString *WebElementLinkURLKey = @"WebElementLinkURL";
NSString *WebElementLinkTargetFrameKey = @"WebElementTargetFrame";
NSString *WebElementLinkLabelKey = @"WebElementLinkLabel";
extern NSString *_WebMainFrameTitleKey;
extern NSString *_WebMainFrameURLKey;
+extern NSString *WebElementTitleKey; // NSString of the title of the element (pending public, used by Safari)
+
typedef enum {
WebDashboardBehaviorAlwaysSendMouseEventsToAllWindows,
WebDashboardBehaviorAlwaysSendActiveNullEventsToPlugIns,