summaryrefslogtreecommitdiffstats
path: root/WebCore/page
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/page')
-rw-r--r--WebCore/page/AXObjectCache.cpp51
-rw-r--r--WebCore/page/AXObjectCache.h7
-rw-r--r--WebCore/page/AccessibilityImageMapLink.cpp2
-rw-r--r--WebCore/page/AccessibilityList.cpp12
-rw-r--r--WebCore/page/AccessibilityListBox.cpp10
-rw-r--r--WebCore/page/AccessibilityListBoxOption.cpp4
-rw-r--r--WebCore/page/AccessibilityObject.cpp27
-rw-r--r--WebCore/page/AccessibilityObject.h6
-rw-r--r--WebCore/page/AccessibilityRenderObject.cpp328
-rw-r--r--WebCore/page/AccessibilityRenderObject.h6
-rw-r--r--WebCore/page/AccessibilityTable.cpp26
-rw-r--r--WebCore/page/AccessibilityTableCell.cpp6
-rw-r--r--WebCore/page/AccessibilityTableColumn.cpp4
-rw-r--r--WebCore/page/AccessibilityTableRow.cpp4
-rw-r--r--WebCore/page/Chrome.cpp25
-rw-r--r--WebCore/page/Chrome.h5
-rw-r--r--WebCore/page/ChromeClient.h21
-rw-r--r--WebCore/page/Console.cpp46
-rw-r--r--WebCore/page/Console.h2
-rw-r--r--WebCore/page/ContextMenuController.cpp17
-rw-r--r--WebCore/page/Coordinates.cpp38
-rw-r--r--WebCore/page/Coordinates.h74
-rw-r--r--WebCore/page/Coordinates.idl41
-rw-r--r--WebCore/page/DOMSelection.cpp103
-rw-r--r--WebCore/page/DOMSelection.h8
-rw-r--r--WebCore/page/DOMSelection.idl38
-rw-r--r--WebCore/page/DOMTimer.cpp22
-rw-r--r--WebCore/page/DOMTimer.h7
-rw-r--r--WebCore/page/DOMWindow.cpp86
-rw-r--r--WebCore/page/DOMWindow.h5
-rw-r--r--WebCore/page/DOMWindow.idl60
-rw-r--r--WebCore/page/DragController.cpp28
-rw-r--r--WebCore/page/EditorClient.h12
-rw-r--r--WebCore/page/EventHandler.cpp264
-rw-r--r--WebCore/page/EventHandler.h14
-rw-r--r--WebCore/page/FocusController.cpp20
-rw-r--r--WebCore/page/Frame.cpp369
-rw-r--r--WebCore/page/Frame.h50
-rw-r--r--WebCore/page/FrameTree.cpp4
-rw-r--r--WebCore/page/FrameTree.h1
-rw-r--r--WebCore/page/FrameView.cpp346
-rw-r--r--WebCore/page/FrameView.h34
-rw-r--r--WebCore/page/Geolocation.cpp44
-rw-r--r--WebCore/page/Geolocation.h25
-rw-r--r--WebCore/page/Geoposition.cpp4
-rw-r--r--WebCore/page/Geoposition.h31
-rw-r--r--WebCore/page/Geoposition.idl8
-rw-r--r--WebCore/page/History.idl9
-rw-r--r--WebCore/page/Location.cpp5
-rw-r--r--WebCore/page/Location.idl16
-rw-r--r--WebCore/page/Navigator.cpp14
-rw-r--r--WebCore/page/NavigatorBase.cpp4
-rw-r--r--WebCore/page/Page.cpp43
-rw-r--r--WebCore/page/Page.h10
-rw-r--r--WebCore/page/PositionOptions.h8
-rw-r--r--WebCore/page/PrintContext.cpp2
-rw-r--r--WebCore/page/SecurityOrigin.cpp21
-rw-r--r--WebCore/page/SecurityOrigin.h6
-rw-r--r--WebCore/page/Settings.cpp42
-rw-r--r--WebCore/page/Settings.h30
-rw-r--r--WebCore/page/WebKitPoint.h63
-rw-r--r--WebCore/page/WebKitPoint.idl33
-rw-r--r--WebCore/page/android/InspectorControllerAndroid.cpp2
-rw-r--r--WebCore/page/animation/AnimationBase.cpp183
-rw-r--r--WebCore/page/animation/AnimationBase.h30
-rw-r--r--WebCore/page/animation/AnimationController.cpp243
-rw-r--r--WebCore/page/animation/AnimationController.h19
-rw-r--r--WebCore/page/animation/AnimationControllerPrivate.h135
-rw-r--r--WebCore/page/animation/CompositeAnimation.cpp139
-rw-r--r--WebCore/page/animation/CompositeAnimation.h22
-rw-r--r--WebCore/page/animation/ImplicitAnimation.cpp77
-rw-r--r--WebCore/page/animation/ImplicitAnimation.h9
-rw-r--r--WebCore/page/animation/KeyframeAnimation.cpp180
-rw-r--r--WebCore/page/animation/KeyframeAnimation.h13
-rw-r--r--WebCore/page/chromium/AccessibilityObjectWrapper.h6
-rw-r--r--WebCore/page/chromium/EventHandlerChromium.cpp6
-rw-r--r--WebCore/page/chromium/FrameChromium.cpp2
-rw-r--r--WebCore/page/gtk/AccessibilityObjectWrapperAtk.cpp4
-rw-r--r--WebCore/page/mac/AXObjectCacheMac.mm6
-rw-r--r--WebCore/page/mac/AccessibilityObjectWrapper.h9
-rw-r--r--WebCore/page/mac/AccessibilityObjectWrapper.mm97
-rw-r--r--WebCore/page/mac/EventHandlerMac.mm6
-rw-r--r--WebCore/page/mac/FrameMac.mm9
-rw-r--r--WebCore/page/win/FrameWin.cpp2
84 files changed, 2564 insertions, 1286 deletions
diff --git a/WebCore/page/AXObjectCache.cpp b/WebCore/page/AXObjectCache.cpp
index d9c4c9a..f8167a5 100644
--- a/WebCore/page/AXObjectCache.cpp
+++ b/WebCore/page/AXObjectCache.cpp
@@ -58,6 +58,7 @@ AXObjectCache::~AXObjectCache()
AccessibilityObject* obj = (*it).second.get();
detachWrapper(obj);
obj->detach();
+ removeAXID(obj);
}
}
@@ -66,39 +67,52 @@ AccessibilityObject* AXObjectCache::get(RenderObject* renderer)
if (!renderer)
return 0;
- RefPtr<AccessibilityObject> obj = 0;
+ AccessibilityObject* obj = 0;
AXID axID = m_renderObjectMapping.get(renderer);
ASSERT(!HashTraits<AXID>::isDeletedValue(axID));
if (axID)
obj = m_objects.get(axID).get();
+
+ return obj;
+}
+
+AccessibilityObject* AXObjectCache::getOrCreate(RenderObject* renderer)
+{
+ if (!renderer)
+ return 0;
+
+ AccessibilityObject* obj = get(renderer);
- Node* element = renderer->element();
if (!obj) {
+ Node* node = renderer->node();
+ RefPtr<AccessibilityObject> newObj = 0;
if (renderer->isListBox())
- obj = AccessibilityListBox::create(renderer);
- else if (element && (element->hasTagName(ulTag) || element->hasTagName(olTag) || element->hasTagName(dlTag)))
- obj = AccessibilityList::create(renderer);
+ newObj = AccessibilityListBox::create(renderer);
+ else if (node && (node->hasTagName(ulTag) || node->hasTagName(olTag) || node->hasTagName(dlTag)))
+ newObj = AccessibilityList::create(renderer);
else if (renderer->isTable())
- obj = AccessibilityTable::create(renderer);
+ newObj = AccessibilityTable::create(renderer);
else if (renderer->isTableRow())
- obj = AccessibilityTableRow::create(renderer);
+ newObj = AccessibilityTableRow::create(renderer);
else if (renderer->isTableCell())
- obj = AccessibilityTableCell::create(renderer);
+ newObj = AccessibilityTableCell::create(renderer);
else
- obj = AccessibilityRenderObject::create(renderer);
+ newObj = AccessibilityRenderObject::create(renderer);
- getAXID(obj.get());
+ obj = newObj.get();
+
+ getAXID(obj);
- m_renderObjectMapping.set(renderer, obj.get()->axObjectID());
- m_objects.set(obj.get()->axObjectID(), obj);
- attachWrapper(obj.get());
+ m_renderObjectMapping.set(renderer, obj->axObjectID());
+ m_objects.set(obj->axObjectID(), obj);
+ attachWrapper(obj);
}
- return obj.get();
+ return obj;
}
-AccessibilityObject* AXObjectCache::get(AccessibilityRole role)
+AccessibilityObject* AXObjectCache::getOrCreate(AccessibilityRole role)
{
RefPtr<AccessibilityObject> obj = 0;
@@ -186,6 +200,9 @@ AXID AXObjectCache::getAXID(AccessibilityObject* obj)
void AXObjectCache::removeAXID(AccessibilityObject* obj)
{
+ if (!obj)
+ return;
+
AXID objID = obj->axObjectID();
if (objID == 0)
return;
@@ -221,7 +238,7 @@ void AXObjectCache::handleActiveDescendantChanged(RenderObject* renderer)
{
if (!renderer)
return;
- AccessibilityObject* obj = get(renderer);
+ AccessibilityObject* obj = getOrCreate(renderer);
if (obj)
obj->handleActiveDescendantChanged();
}
@@ -230,7 +247,7 @@ void AXObjectCache::handleAriaRoleChanged(RenderObject* renderer)
{
if (!renderer)
return;
- AccessibilityObject* obj = get(renderer);
+ AccessibilityObject* obj = getOrCreate(renderer);
if (obj && obj->isAccessibilityRenderObject())
static_cast<AccessibilityRenderObject*>(obj)->setAriaRole();
}
diff --git a/WebCore/page/AXObjectCache.h b/WebCore/page/AXObjectCache.h
index 5e95f74..4fd6dc3 100644
--- a/WebCore/page/AXObjectCache.h
+++ b/WebCore/page/AXObjectCache.h
@@ -60,10 +60,13 @@ namespace WebCore {
~AXObjectCache();
// to be used with render objects
- AccessibilityObject* get(RenderObject*);
+ AccessibilityObject* getOrCreate(RenderObject*);
// used for objects without backing elements
- AccessibilityObject* get(AccessibilityRole);
+ AccessibilityObject* getOrCreate(AccessibilityRole);
+
+ // will only return the AccessibilityObject if it already exists
+ AccessibilityObject* get(RenderObject*);
void remove(RenderObject*);
void remove(AXID);
diff --git a/WebCore/page/AccessibilityImageMapLink.cpp b/WebCore/page/AccessibilityImageMapLink.cpp
index 5557446..86ca623 100644
--- a/WebCore/page/AccessibilityImageMapLink.cpp
+++ b/WebCore/page/AccessibilityImageMapLink.cpp
@@ -65,7 +65,7 @@ AccessibilityObject* AccessibilityImageMapLink::parentObject() const
if (!m_mapElement || !m_mapElement->renderer())
return 0;
- return m_mapElement->document()->axObjectCache()->get(m_mapElement->renderer());
+ return m_mapElement->document()->axObjectCache()->getOrCreate(m_mapElement->renderer());
}
Element* AccessibilityImageMapLink::actionElement() const
diff --git a/WebCore/page/AccessibilityList.cpp b/WebCore/page/AccessibilityList.cpp
index ad71ff4..3097b3b 100644
--- a/WebCore/page/AccessibilityList.cpp
+++ b/WebCore/page/AccessibilityList.cpp
@@ -68,8 +68,8 @@ bool AccessibilityList::isUnorderedList() const
if (!m_renderer)
return false;
- Node* element = m_renderer->element();
- return element && element->hasTagName(ulTag);
+ Node* node = m_renderer->node();
+ return node && node->hasTagName(ulTag);
}
bool AccessibilityList::isOrderedList() const
@@ -77,8 +77,8 @@ bool AccessibilityList::isOrderedList() const
if (!m_renderer)
return false;
- Node* element = m_renderer->element();
- return element && element->hasTagName(olTag);
+ Node* node = m_renderer->node();
+ return node && node->hasTagName(olTag);
}
bool AccessibilityList::isDefinitionList() const
@@ -86,8 +86,8 @@ bool AccessibilityList::isDefinitionList() const
if (!m_renderer)
return false;
- Node* element = m_renderer->element();
- return element && element->hasTagName(dlTag);
+ Node* node = m_renderer->node();
+ return node && node->hasTagName(dlTag);
}
diff --git a/WebCore/page/AccessibilityListBox.cpp b/WebCore/page/AccessibilityListBox.cpp
index b94ccef..37baec9 100644
--- a/WebCore/page/AccessibilityListBox.cpp
+++ b/WebCore/page/AccessibilityListBox.cpp
@@ -144,7 +144,7 @@ AccessibilityObject* AccessibilityListBox::listBoxOptionAccessibilityObject(HTML
if (!element || element->hasTagName(hrTag))
return 0;
- AccessibilityObject* listBoxObject = m_renderer->document()->axObjectCache()->get(ListBoxOptionRole);
+ AccessibilityObject* listBoxObject = m_renderer->document()->axObjectCache()->getOrCreate(ListBoxOptionRole);
static_cast<AccessibilityListBoxOption*>(listBoxObject)->setHTMLElement(element);
return listBoxObject;
@@ -157,13 +157,13 @@ AccessibilityObject* AccessibilityListBox::doAccessibilityHitTest(const IntPoint
if (!m_renderer)
return 0;
- Node* element = m_renderer->element();
- if (!element)
+ Node* node = m_renderer->node();
+ if (!node)
return 0;
IntRect parentRect = boundingBoxRect();
- const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(element)->listItems();
+ const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(node)->listItems();
unsigned length = listItems.size();
for (unsigned i = 0; i < length; i++) {
IntRect rect = static_cast<RenderListBox*>(m_renderer)->itemBoundingBoxRect(parentRect.x(), parentRect.y(), i);
@@ -171,7 +171,7 @@ AccessibilityObject* AccessibilityListBox::doAccessibilityHitTest(const IntPoint
return listBoxOptionAccessibilityObject(listItems[i]);
}
- return axObjectCache()->get(m_renderer);
+ return axObjectCache()->getOrCreate(m_renderer);
}
} // namespace WebCore
diff --git a/WebCore/page/AccessibilityListBoxOption.cpp b/WebCore/page/AccessibilityListBoxOption.cpp
index fedfe91..088c556 100644
--- a/WebCore/page/AccessibilityListBoxOption.cpp
+++ b/WebCore/page/AccessibilityListBoxOption.cpp
@@ -97,7 +97,7 @@ IntRect AccessibilityListBoxOption::elementRect() const
if (!listBoxRenderer)
return rect;
- IntRect parentRect = listBoxRenderer->document()->axObjectCache()->get(listBoxRenderer)->boundingBoxRect();
+ IntRect parentRect = listBoxRenderer->document()->axObjectCache()->getOrCreate(listBoxRenderer)->boundingBoxRect();
int index = listBoxOptionIndex();
if (index != -1)
rect = static_cast<RenderListBox*>(listBoxRenderer)->itemBoundingBoxRect(parentRect.x(), parentRect.y(), index);
@@ -153,7 +153,7 @@ AccessibilityObject* AccessibilityListBoxOption::parentObject() const
if (!parentNode)
return 0;
- return m_optionElement->document()->axObjectCache()->get(parentNode->renderer());
+ return m_optionElement->document()->axObjectCache()->getOrCreate(parentNode->renderer());
}
void AccessibilityListBoxOption::setSelected(bool selected)
diff --git a/WebCore/page/AccessibilityObject.cpp b/WebCore/page/AccessibilityObject.cpp
index 6d441d0..d5b7ff5 100644
--- a/WebCore/page/AccessibilityObject.cpp
+++ b/WebCore/page/AccessibilityObject.cpp
@@ -75,7 +75,6 @@ AccessibilityObject::~AccessibilityObject()
void AccessibilityObject::detach()
{
- removeAXObjectID();
#if HAVE(ACCESSIBILITY)
setWrapper(0);
#endif
@@ -114,6 +113,11 @@ AccessibilityObject* AccessibilityObject::parentObjectUnignored() const
return parent;
}
+AccessibilityObject* AccessibilityObject::parentObjectIfExists() const
+{
+ return 0;
+}
+
int AccessibilityObject::layoutCount() const
{
return 0;
@@ -231,9 +235,9 @@ const AtomicString& AccessibilityObject::accessKey() const
return nullAtom;
}
-Selection AccessibilityObject::selection() const
+VisibleSelection AccessibilityObject::selection() const
{
- return Selection();
+ return VisibleSelection();
}
PlainTextRange AccessibilityObject::selectedTextRange() const
@@ -357,7 +361,7 @@ VisiblePositionRange AccessibilityObject::visiblePositionRangeForUnorderedPositi
// use selection order to see if the positions are in order
else
- alreadyInOrder = Selection(visiblePos1, visiblePos2).isBaseFirst();
+ alreadyInOrder = VisibleSelection(visiblePos1, visiblePos2).isBaseFirst();
if (alreadyInOrder) {
startPos = visiblePos1;
@@ -400,7 +404,7 @@ static VisiblePosition updateAXLineStartForVisiblePosition(const VisiblePosition
if (!p.node())
break;
renderer = p.node()->renderer();
- if (!renderer || renderer->isRenderBlock() && !p.offset())
+ if (!renderer || (renderer->isRenderBlock() && !p.m_offset))
break;
InlineBox* box;
int ignoredCaretOffset;
@@ -514,7 +518,7 @@ static VisiblePosition startOfStyleRange(const VisiblePosition visiblePos)
return VisiblePosition(startRenderer->node(), 0, VP_DEFAULT_AFFINITY);
}
-static VisiblePosition endOfStyleRange(const VisiblePosition visiblePos)
+static VisiblePosition endOfStyleRange(const VisiblePosition& visiblePos)
{
RenderObject* renderer = visiblePos.deepEquivalent().node()->renderer();
RenderObject* endRenderer = renderer;
@@ -534,7 +538,7 @@ static VisiblePosition endOfStyleRange(const VisiblePosition visiblePos)
endRenderer = r;
}
- return VisiblePosition(endRenderer->node(), maxDeepOffset(endRenderer->node()), VP_DEFAULT_AFFINITY);
+ return lastDeepEditingPositionForNode(endRenderer->node());
}
VisiblePositionRange AccessibilityObject::styleRangeForPosition(const VisiblePosition& visiblePos) const
@@ -566,7 +570,7 @@ static bool replacedNodeNeedsCharacter(Node* replacedNode)
}
// create an AX object, but skip it if it is not supposed to be seen
- AccessibilityObject* object = replacedNode->renderer()->document()->axObjectCache()->get(replacedNode->renderer());
+ AccessibilityObject* object = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
if (object->accessibilityIsIgnored())
return false;
@@ -814,7 +818,7 @@ AccessibilityObject* AccessibilityObject::accessibilityObjectForPosition(const V
if (!obj)
return 0;
- return obj->document()->axObjectCache()->get(obj);
+ return obj->document()->axObjectCache()->getOrCreate(obj);
}
int AccessibilityObject::lineForPosition(const VisiblePosition& visiblePos) const
@@ -996,11 +1000,6 @@ void AccessibilityObject::setAXObjectID(unsigned axObjectID)
m_id = axObjectID;
}
-void AccessibilityObject::removeAXObjectID()
-{
- return;
-}
-
const String& AccessibilityObject::actionVerb() const
{
// FIXME: Need to add verbs for select elements.
diff --git a/WebCore/page/AccessibilityObject.h b/WebCore/page/AccessibilityObject.h
index a751003..9141b36 100644
--- a/WebCore/page/AccessibilityObject.h
+++ b/WebCore/page/AccessibilityObject.h
@@ -83,7 +83,7 @@ class IntPoint;
class IntSize;
class Node;
class RenderObject;
-class Selection;
+class VisibleSelection;
class String;
class Widget;
@@ -266,6 +266,7 @@ public:
virtual AccessibilityObject* nextSibling() const;
virtual AccessibilityObject* parentObject() const;
virtual AccessibilityObject* parentObjectUnignored() const;
+ virtual AccessibilityObject* parentObjectIfExists() const;
virtual AccessibilityObject* observableObject() const;
virtual void linkedUIElements(AccessibilityChildrenVector&) const;
virtual AccessibilityObject* titleUIElement() const;
@@ -285,7 +286,7 @@ public:
virtual KURL url() const;
virtual PlainTextRange selectedTextRange() const;
- virtual Selection selection() const;
+ virtual VisibleSelection selection() const;
unsigned selectionStart() const;
unsigned selectionEnd() const;
virtual String stringValue() const;
@@ -410,7 +411,6 @@ protected:
mutable bool m_haveChildren;
virtual void clearChildren();
- virtual void removeAXObjectID();
virtual bool isDetached() const { return true; }
#if PLATFORM(MAC)
diff --git a/WebCore/page/AccessibilityRenderObject.cpp b/WebCore/page/AccessibilityRenderObject.cpp
index 5cdc7b4..8ed352a 100644
--- a/WebCore/page/AccessibilityRenderObject.cpp
+++ b/WebCore/page/AccessibilityRenderObject.cpp
@@ -58,6 +58,7 @@
#include "RenderFieldset.h"
#include "RenderFileUploadControl.h"
#include "RenderImage.h"
+#include "RenderInline.h"
#include "RenderListBox.h"
#include "RenderListMarker.h"
#include "RenderMenuList.h"
@@ -120,7 +121,7 @@ AccessibilityObject* AccessibilityRenderObject::firstChild() const
if (!firstChild)
return 0;
- return m_renderer->document()->axObjectCache()->get(firstChild);
+ return m_renderer->document()->axObjectCache()->getOrCreate(firstChild);
}
AccessibilityObject* AccessibilityRenderObject::lastChild() const
@@ -132,7 +133,7 @@ AccessibilityObject* AccessibilityRenderObject::lastChild() const
if (!lastChild)
return 0;
- return m_renderer->document()->axObjectCache()->get(lastChild);
+ return m_renderer->document()->axObjectCache()->getOrCreate(lastChild);
}
AccessibilityObject* AccessibilityRenderObject::previousSibling() const
@@ -144,7 +145,7 @@ AccessibilityObject* AccessibilityRenderObject::previousSibling() const
if (!previousSibling)
return 0;
- return m_renderer->document()->axObjectCache()->get(previousSibling);
+ return m_renderer->document()->axObjectCache()->getOrCreate(previousSibling);
}
AccessibilityObject* AccessibilityRenderObject::nextSibling() const
@@ -156,9 +157,21 @@ AccessibilityObject* AccessibilityRenderObject::nextSibling() const
if (!nextSibling)
return 0;
- return m_renderer->document()->axObjectCache()->get(nextSibling);
+ return m_renderer->document()->axObjectCache()->getOrCreate(nextSibling);
}
+AccessibilityObject* AccessibilityRenderObject::parentObjectIfExists() const
+{
+ if (!m_renderer)
+ return 0;
+
+ RenderObject *parent = m_renderer->parent();
+ if (!parent)
+ return 0;
+
+ return m_renderer->document()->axObjectCache()->get(parent);
+}
+
AccessibilityObject* AccessibilityRenderObject::parentObject() const
{
if (!m_renderer)
@@ -169,7 +182,7 @@ AccessibilityObject* AccessibilityRenderObject::parentObject() const
return 0;
if (ariaRoleAttribute() == MenuBarRole)
- return m_renderer->document()->axObjectCache()->get(parent);
+ return m_renderer->document()->axObjectCache()->getOrCreate(parent);
// menuButton and its corresponding menu are DOM siblings, but Accessibility needs them to be parent/child
if (ariaRoleAttribute() == MenuRole) {
@@ -178,7 +191,7 @@ AccessibilityObject* AccessibilityRenderObject::parentObject() const
return parent;
}
- return m_renderer->document()->axObjectCache()->get(parent);
+ return m_renderer->document()->axObjectCache()->getOrCreate(parent);
}
bool AccessibilityRenderObject::isWebArea() const
@@ -198,7 +211,7 @@ bool AccessibilityRenderObject::isAnchor() const
bool AccessibilityRenderObject::isNativeTextControl() const
{
- return m_renderer->isTextField() || m_renderer->isTextArea();
+ return m_renderer->isTextControl();
}
bool AccessibilityRenderObject::isTextControl() const
@@ -219,6 +232,9 @@ bool AccessibilityRenderObject::isImage() const
bool AccessibilityRenderObject::isAttachment() const
{
+ if (!m_renderer)
+ return false;
+
// Widgets are the replaced elements that we represent to AX as attachments
bool isWidget = m_renderer && m_renderer->isWidget();
ASSERT(!isWidget || (m_renderer->isReplaced() && !isImage()));
@@ -228,9 +244,16 @@ bool AccessibilityRenderObject::isAttachment() const
bool AccessibilityRenderObject::isPasswordField() const
{
ASSERT(m_renderer);
- if (!m_renderer->element() || !m_renderer->element()->isHTMLElement())
+ if (!m_renderer->node() || !m_renderer->node()->isHTMLElement())
+ return false;
+ if (ariaRoleAttribute() != UnknownRole)
+ return false;
+
+ InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node()));
+ if (!inputElement)
return false;
- return static_cast<HTMLElement*>(m_renderer->element())->isPasswordField() && ariaRoleAttribute() == UnknownRole;
+
+ return inputElement->isPasswordField();
}
bool AccessibilityRenderObject::isCheckboxOrRadio() const
@@ -241,8 +264,8 @@ bool AccessibilityRenderObject::isCheckboxOrRadio() const
bool AccessibilityRenderObject::isFileUploadButton() const
{
- if (m_renderer && m_renderer->element() && m_renderer->element()->hasTagName(inputTag)) {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
+ if (m_renderer && m_renderer->node() && m_renderer->node()->hasTagName(inputTag)) {
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->node());
return input->inputType() == HTMLInputElement::FILE;
}
@@ -251,8 +274,8 @@ bool AccessibilityRenderObject::isFileUploadButton() const
bool AccessibilityRenderObject::isInputImage() const
{
- if (m_renderer && m_renderer->element() && m_renderer->element()->hasTagName(inputTag)) {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
+ if (m_renderer && m_renderer->node() && m_renderer->node()->hasTagName(inputTag)) {
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->node());
return input->inputType() == HTMLInputElement::IMAGE;
}
@@ -321,13 +344,27 @@ bool AccessibilityRenderObject::isPressed() const
bool AccessibilityRenderObject::isIndeterminate() const
{
ASSERT(m_renderer);
- return m_renderer->node() && m_renderer->node()->isIndeterminate();
+ if (!m_renderer->node() || !m_renderer->node()->isElementNode())
+ return false;
+
+ InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node()));
+ if (!inputElement)
+ return false;
+
+ return inputElement->isIndeterminate();
}
bool AccessibilityRenderObject::isChecked() const
{
ASSERT(m_renderer);
- return m_renderer->node() && m_renderer->node()->isChecked();
+ if (!m_renderer->node() || !m_renderer->node()->isElementNode())
+ return false;
+
+ InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node()));
+ if (!inputElement)
+ return false;
+
+ return inputElement->isChecked();
}
bool AccessibilityRenderObject::isHovered() const
@@ -341,7 +378,7 @@ bool AccessibilityRenderObject::isMultiSelect() const
ASSERT(m_renderer);
if (!m_renderer->isListBox())
return false;
- return m_renderer->element() && static_cast<HTMLSelectElement*>(m_renderer->element())->multiple();
+ return m_renderer->node() && static_cast<HTMLSelectElement*>(m_renderer->node())->multiple();
}
bool AccessibilityRenderObject::isReadOnly() const
@@ -384,7 +421,7 @@ int AccessibilityRenderObject::headingLevel(Node* node)
return 0;
if (RenderObject* renderer = node->renderer()) {
- AccessibilityObject* axObjectForNode = node->document()->axObjectCache()->get(renderer);
+ AccessibilityObject* axObjectForNode = node->document()->axObjectCache()->getOrCreate(renderer);
if (axObjectForNode->ariaRoleAttribute() == HeadingRole) {
if (!node->isElementNode())
return 0;
@@ -430,8 +467,9 @@ bool AccessibilityRenderObject::isControl() const
if (!m_renderer)
return false;
- Node* node = m_renderer->element();
- return node && (node->isControl() || AccessibilityObject::isARIAControl(ariaRoleAttribute()));
+ Node* node = m_renderer->node();
+ return node && ((node->isElementNode() && static_cast<Element*>(node)->isFormControlElement())
+ || AccessibilityObject::isARIAControl(ariaRoleAttribute()));
}
bool AccessibilityRenderObject::isFieldset() const
@@ -449,7 +487,7 @@ bool AccessibilityRenderObject::isGroup() const
const AtomicString& AccessibilityRenderObject::getAttribute(const QualifiedName& attribute) const
{
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (!node)
return nullAtom;
@@ -469,10 +507,12 @@ Element* AccessibilityRenderObject::anchorElement() const
RenderObject* currRenderer;
// Search up the render tree for a RenderObject with a DOM node. Defer to an earlier continuation, though.
- for (currRenderer = m_renderer; currRenderer && !currRenderer->element(); currRenderer = currRenderer->parent()) {
- RenderFlow* continuation = currRenderer->virtualContinuation();
- if (continuation)
- return cache->get(continuation)->anchorElement();
+ for (currRenderer = m_renderer; currRenderer && !currRenderer->node(); currRenderer = currRenderer->parent()) {
+ if (currRenderer->isRenderBlock()) {
+ RenderInline* continuation = toRenderBlock(currRenderer)->inlineContinuation();
+ if (continuation)
+ return cache->getOrCreate(continuation)->anchorElement();
+ }
}
// bail if none found
@@ -483,7 +523,7 @@ Element* AccessibilityRenderObject::anchorElement() const
// NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
Node* node = currRenderer->node();
for ( ; node; node = node->parentNode()) {
- if (node->hasTagName(aTag) || (node->renderer() && cache->get(node->renderer())->isAnchor()))
+ if (node->hasTagName(aTag) || (node->renderer() && cache->getOrCreate(node->renderer())->isAnchor()))
return static_cast<Element*>(node);
}
@@ -495,7 +535,7 @@ Element* AccessibilityRenderObject::actionElement() const
if (!m_renderer)
return 0;
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (node) {
if (node->hasTagName(inputTag)) {
HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
@@ -506,13 +546,13 @@ Element* AccessibilityRenderObject::actionElement() const
}
if (isFileUploadButton())
- return static_cast<Element*>(m_renderer->element());
+ return static_cast<Element*>(m_renderer->node());
if (AccessibilityObject::isARIAInput(ariaRoleAttribute()))
- return static_cast<Element*>(m_renderer->element());
+ return static_cast<Element*>(m_renderer->node());
if (isImageButton())
- return static_cast<Element*>(m_renderer->element());
+ return static_cast<Element*>(m_renderer->node());
if (m_renderer->isMenuList())
return static_cast<RenderMenuList*>(m_renderer)->selectElement();
@@ -525,18 +565,18 @@ Element* AccessibilityRenderObject::actionElement() const
Element* AccessibilityRenderObject::mouseButtonListener() const
{
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (!node)
return 0;
- if (!node->isEventTargetNode())
+ if (!node->isElementNode())
return 0;
-
+
// FIXME: Do the continuation search like anchorElement does
- for (EventTargetNode* elt = static_cast<EventTargetNode*>(node); elt; elt = static_cast<EventTargetNode*>(elt->parentNode())) {
- if (elt->inlineEventListenerForType(eventNames().clickEvent) || elt->inlineEventListenerForType(eventNames().mousedownEvent) || elt->inlineEventListenerForType(eventNames().mouseupEvent))
- return static_cast<Element*>(elt);
+ for (Element* element = static_cast<Element*>(node); element; element = element->parentElement()) {
+ if (element->inlineEventListenerForType(eventNames().clickEvent) || element->inlineEventListenerForType(eventNames().mousedownEvent) || element->inlineEventListenerForType(eventNames().mouseupEvent))
+ return element;
}
-
+
return 0;
}
@@ -567,7 +607,7 @@ AccessibilityObject* AccessibilityRenderObject::menuForMenuButton() const
{
Element* menu = menuElementForMenuButton();
if (menu && menu->renderer())
- return m_renderer->document()->axObjectCache()->get(menu->renderer());
+ return m_renderer->document()->axObjectCache()->getOrCreate(menu->renderer());
return 0;
}
@@ -585,7 +625,7 @@ AccessibilityObject* AccessibilityRenderObject::menuButtonForMenu() const
if (menuItem && menuItem->renderer()) {
// ARIA just has generic menu items. AppKit needs to know if this is a top level items like MenuBarButton or MenuBarItem
- AccessibilityObject* menuItemAX = m_renderer->document()->axObjectCache()->get(menuItem->renderer());
+ AccessibilityObject* menuItemAX = m_renderer->document()->axObjectCache()->getOrCreate(menuItem->renderer());
if (menuItemAX->isMenuButton())
return menuItemAX;
}
@@ -598,11 +638,11 @@ String AccessibilityRenderObject::helpText() const
return String();
for (RenderObject* curr = m_renderer; curr; curr = curr->parent()) {
- if (curr->element() && curr->element()->isHTMLElement()) {
- const AtomicString& summary = static_cast<Element*>(curr->element())->getAttribute(summaryAttr);
+ if (curr->node() && curr->node()->isHTMLElement()) {
+ const AtomicString& summary = static_cast<Element*>(curr->node())->getAttribute(summaryAttr);
if (!summary.isEmpty())
return summary;
- const AtomicString& title = static_cast<Element*>(curr->element())->getAttribute(titleAttr);
+ const AtomicString& title = static_cast<Element*>(curr->node())->getAttribute(titleAttr);
if (!title.isEmpty())
return title;
}
@@ -621,7 +661,7 @@ String AccessibilityRenderObject::textUnderElement() const
return uploadControl->buttonValue();
}
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (node) {
if (Frame* frame = node->document()->frame()) {
// catch stale WebCoreAXObject (see <rdar://problem/3960196>)
@@ -641,7 +681,7 @@ bool AccessibilityRenderObject::hasIntValue() const
if (isHeading())
return true;
- if (m_renderer->element() && isCheckboxOrRadio())
+ if (m_renderer->node() && isCheckboxOrRadio())
return true;
return false;
@@ -653,9 +693,9 @@ int AccessibilityRenderObject::intValue() const
return 0;
if (isHeading())
- return headingLevel(m_renderer->element());
+ return headingLevel(m_renderer->node());
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (!node || !isCheckboxOrRadio())
return 0;
@@ -830,7 +870,7 @@ HTMLLabelElement* AccessibilityRenderObject::labelElementContainer() const
return false;
// find if this has a parent that is a label
- for (Node* parentNode = m_renderer->element(); parentNode; parentNode = parentNode->parentNode()) {
+ for (Node* parentNode = m_renderer->node(); parentNode; parentNode = parentNode->parentNode()) {
if (parentNode->hasTagName(labelTag))
return static_cast<HTMLLabelElement*>(parentNode);
}
@@ -845,7 +885,7 @@ String AccessibilityRenderObject::title() const
if (!m_renderer)
return String();
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (!node)
return String();
@@ -901,9 +941,10 @@ String AccessibilityRenderObject::accessibilityDescription() const
if (!ariaDescription.isEmpty())
return ariaDescription;
- if (isImage()) {
- if (m_renderer->element() && m_renderer->element()->isHTMLElement()) {
- const AtomicString& alt = static_cast<HTMLElement*>(m_renderer->element())->getAttribute(altAttr);
+ if (isImage() || isInputImage()) {
+ Node* node = m_renderer->node();
+ if (node && node->isHTMLElement()) {
+ const AtomicString& alt = static_cast<HTMLElement*>(node)->getAttribute(altAttr);
if (alt.isEmpty())
return String();
return alt;
@@ -944,8 +985,8 @@ IntRect AccessibilityRenderObject::boundingBoxRect() const
if (!obj)
return IntRect();
- if (obj->isInlineContinuation())
- obj = obj->element()->renderer();
+ if (obj->node()) // If we are a continuation, we want to make sure to use the primary renderer.
+ obj = obj->node()->renderer();
// FIXME: This doesn't work correctly with transforms.
Vector<IntRect> rects;
@@ -968,11 +1009,11 @@ IntRect AccessibilityRenderObject::checkboxOrRadioRect() const
if (!m_renderer)
return IntRect();
- HTMLLabelElement* label = labelForElement(static_cast<Element*>(m_renderer->element()));
+ HTMLLabelElement* label = labelForElement(static_cast<Element*>(m_renderer->node()));
if (!label || !label->renderer())
return boundingBoxRect();
- IntRect labelRect = axObjectCache()->get(label->renderer())->elementRect();
+ IntRect labelRect = axObjectCache()->getOrCreate(label->renderer())->elementRect();
labelRect.unite(boundingBoxRect());
return labelRect;
}
@@ -1018,7 +1059,7 @@ AccessibilityObject* AccessibilityRenderObject::internalLinkElement() const
return 0;
// the element we find may not be accessible, keep searching until we find a good one
- AccessibilityObject* linkedAXElement = m_renderer->document()->axObjectCache()->get(linkedNode->renderer());
+ AccessibilityObject* linkedAXElement = m_renderer->document()->axObjectCache()->getOrCreate(linkedNode->renderer());
while (linkedAXElement && linkedAXElement->accessibilityIsIgnored()) {
linkedNode = linkedNode->traverseNextNode();
@@ -1027,7 +1068,7 @@ AccessibilityObject* AccessibilityRenderObject::internalLinkElement() const
if (!linkedNode)
return 0;
- linkedAXElement = m_renderer->document()->axObjectCache()->get(linkedNode->renderer());
+ linkedAXElement = m_renderer->document()->axObjectCache()->getOrCreate(linkedNode->renderer());
}
return linkedAXElement;
@@ -1051,7 +1092,7 @@ void AccessibilityRenderObject::addRadioButtonGroupMembers(AccessibilityChildren
unsigned len = formElements.size();
for (unsigned i = 0; i < len; ++i) {
Node* associateElement = formElements[i].get();
- if (AccessibilityObject* object = m_renderer->document()->axObjectCache()->get(associateElement->renderer()))
+ if (AccessibilityObject* object = m_renderer->document()->axObjectCache()->getOrCreate(associateElement->renderer()))
linkedUIElements.append(object);
}
} else {
@@ -1061,7 +1102,7 @@ void AccessibilityRenderObject::addRadioButtonGroupMembers(AccessibilityChildren
if (list->item(i)->hasTagName(inputTag)) {
HTMLInputElement* associateElement = static_cast<HTMLInputElement*>(list->item(i));
if (associateElement->isRadioButton() && associateElement->name() == input->name()) {
- if (AccessibilityObject* object = m_renderer->document()->axObjectCache()->get(associateElement->renderer()))
+ if (AccessibilityObject* object = m_renderer->document()->axObjectCache()->getOrCreate(associateElement->renderer()))
linkedUIElements.append(object);
}
}
@@ -1090,16 +1131,16 @@ AccessibilityObject* AccessibilityRenderObject::titleUIElement() const
// if isFieldset is true, the renderer is guaranteed to be a RenderFieldset
if (isFieldset())
- return axObjectCache()->get(static_cast<RenderFieldset*>(m_renderer)->findLegend());
+ return axObjectCache()->getOrCreate(static_cast<RenderFieldset*>(m_renderer)->findLegend());
// checkbox and radio hide their labels. Only controls get titleUIElements for now
if (isCheckboxOrRadio() || !isControl())
return 0;
- Node* element = m_renderer->element();
+ Node* element = m_renderer->node();
HTMLLabelElement* label = labelForElement(static_cast<Element*>(element));
if (label && label->renderer())
- return axObjectCache()->get(label->renderer());
+ return axObjectCache()->getOrCreate(label->renderer());
return 0;
}
@@ -1125,7 +1166,7 @@ bool AccessibilityRenderObject::accessibilityIsIgnored() const
if (labelElement) {
HTMLElement* correspondingControl = labelElement->correspondingControl();
if (correspondingControl && correspondingControl->renderer()) {
- AccessibilityObject* controlObject = axObjectCache()->get(correspondingControl->renderer());
+ AccessibilityObject* controlObject = axObjectCache()->getOrCreate(correspondingControl->renderer());
if (controlObject->isCheckboxOrRadio())
return true;
}
@@ -1157,12 +1198,12 @@ bool AccessibilityRenderObject::accessibilityIsIgnored() const
return false;
// don't ignore labels, because they serve as TitleUIElements
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (node && node->hasTagName(labelTag))
return false;
if (m_renderer->isBlockFlow() && m_renderer->childrenInline())
- return !static_cast<RenderBlock*>(m_renderer)->firstLineBox() && !mouseButtonListener();
+ return !toRenderBlock(m_renderer)->firstLineBox() && !mouseButtonListener();
// ignore images seemingly used as spacers
if (isImage()) {
@@ -1178,7 +1219,7 @@ bool AccessibilityRenderObject::accessibilityIsIgnored() const
}
// check for one-dimensional image
- RenderImage* image = static_cast<RenderImage*>(m_renderer);
+ RenderImage* image = toRenderImage(m_renderer);
if (image->height() <= 1 || image->width() <= 1)
return true;
@@ -1211,7 +1252,7 @@ int AccessibilityRenderObject::layoutCount() const
{
if (!m_renderer->isRenderView())
return 0;
- return static_cast<RenderView*>(m_renderer)->frameView()->layoutCount();
+ return toRenderView(m_renderer)->frameView()->layoutCount();
}
String AccessibilityRenderObject::text() const
@@ -1220,9 +1261,9 @@ String AccessibilityRenderObject::text() const
return String();
if (isNativeTextControl())
- return static_cast<RenderTextControl*>(m_renderer)->text();
+ return toRenderTextControl(m_renderer)->text();
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (!node)
return String();
if (!node->isElementNode())
@@ -1243,11 +1284,11 @@ int AccessibilityRenderObject::textLength() const
PassRefPtr<Range> AccessibilityRenderObject::ariaSelectedTextDOMRange() const
{
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (!node)
return 0;
- RefPtr<Range> currentSelectionRange = selection().toRange();
+ RefPtr<Range> currentSelectionRange = selection().toNormalizedRange();
if (!currentSelectionRange)
return 0;
@@ -1280,7 +1321,7 @@ String AccessibilityRenderObject::selectedText() const
return String(); // need to return something distinct from empty string
if (isNativeTextControl()) {
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
+ RenderTextControl* textControl = toRenderTextControl(m_renderer);
return textControl->text().substring(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
}
@@ -1295,7 +1336,7 @@ String AccessibilityRenderObject::selectedText() const
const AtomicString& AccessibilityRenderObject::accessKey() const
{
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (!node)
return nullAtom;
if (!node->isElementNode())
@@ -1303,7 +1344,7 @@ const AtomicString& AccessibilityRenderObject::accessKey() const
return static_cast<Element*>(node)->getAttribute(accesskeyAttr);
}
-Selection AccessibilityRenderObject::selection() const
+VisibleSelection AccessibilityRenderObject::selection() const
{
return m_renderer->document()->frame()->selection()->selection();
}
@@ -1317,7 +1358,7 @@ PlainTextRange AccessibilityRenderObject::selectedTextRange() const
AccessibilityRole ariaRole = ariaRoleAttribute();
if (isNativeTextControl() && ariaRole == UnknownRole) {
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
+ RenderTextControl* textControl = toRenderTextControl(m_renderer);
return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
}
@@ -1333,7 +1374,7 @@ PlainTextRange AccessibilityRenderObject::selectedTextRange() const
void AccessibilityRenderObject::setSelectedTextRange(const PlainTextRange& range)
{
if (isNativeTextControl()) {
- RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
+ RenderTextControl* textControl = toRenderTextControl(m_renderer);
textControl->setSelectionRange(range.start, range.start + range.length);
return;
}
@@ -1344,14 +1385,14 @@ void AccessibilityRenderObject::setSelectedTextRange(const PlainTextRange& range
Frame* frame = document->frame();
if (!frame)
return;
- Node* node = m_renderer->element();
- frame->selection()->setSelection(Selection(Position(node, range.start),
+ Node* node = m_renderer->node();
+ frame->selection()->setSelection(VisibleSelection(Position(node, range.start),
Position(node, range.start + range.length), DOWNSTREAM));
}
KURL AccessibilityRenderObject::url() const
{
- if (isAnchor() && m_renderer->element()->hasTagName(aTag)) {
+ if (isAnchor() && m_renderer->node()->hasTagName(aTag)) {
if (HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(anchorElement()))
return anchor->href();
}
@@ -1359,11 +1400,11 @@ KURL AccessibilityRenderObject::url() const
if (isWebArea())
return m_renderer->document()->url();
- if (isImage() && m_renderer->element() && m_renderer->element()->hasTagName(imgTag))
- return static_cast<HTMLImageElement*>(m_renderer->element())->src();
+ if (isImage() && m_renderer->node() && m_renderer->node()->hasTagName(imgTag))
+ return static_cast<HTMLImageElement*>(m_renderer->node())->src();
if (isInputImage())
- return static_cast<HTMLInputElement*>(m_renderer->element())->src();
+ return static_cast<HTMLInputElement*>(m_renderer->node())->src();
return KURL();
}
@@ -1400,7 +1441,7 @@ bool AccessibilityRenderObject::isFocused() const
// A web area is represented by the Document node in the DOM tree, which isn't focusable.
// Check instead if the frame's selection controller is focused
- if (focusedNode == m_renderer->element() ||
+ if (focusedNode == m_renderer->node() ||
(roleValue() == WebAreaRole && document->frame()->selection()->isFocusedAndActive()))
return true;
@@ -1415,10 +1456,10 @@ void AccessibilityRenderObject::setFocused(bool on)
if (!on)
m_renderer->document()->setFocusedNode(0);
else {
- if (m_renderer->element()->isElementNode())
- static_cast<Element*>(m_renderer->element())->focus();
+ if (m_renderer->node()->isElementNode())
+ static_cast<Element*>(m_renderer->node())->focus();
else
- m_renderer->document()->setFocusedNode(m_renderer->element());
+ m_renderer->document()->setFocusedNode(m_renderer->node());
}
}
@@ -1426,17 +1467,25 @@ void AccessibilityRenderObject::setValue(const String& string)
{
// FIXME: Do we want to do anything here for ARIA textboxes?
if (m_renderer->isTextField()) {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->node());
input->setValue(string);
} else if (m_renderer->isTextArea()) {
- HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(m_renderer->element());
+ HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(m_renderer->node());
textArea->setValue(string);
}
}
bool AccessibilityRenderObject::isEnabled() const
{
- return m_renderer->element() ? m_renderer->element()->isEnabled() : true;
+ ASSERT(m_renderer);
+ if (!m_renderer->node() || !m_renderer->node()->isElementNode())
+ return true;
+
+ FormControlElement* formControlElement = toFormControlElement(static_cast<Element*>(m_renderer->node()));
+ if (!formControlElement)
+ return true;
+
+ return formControlElement->isEnabled();
}
RenderView* AccessibilityRenderObject::topRenderer() const
@@ -1482,7 +1531,7 @@ AccessibilityObject* AccessibilityRenderObject::accessibilityParentForImageMap(H
// The HTMLImageElement's useMap() value includes the '#' symbol at the beginning,
// which has to be stripped off
if (static_cast<HTMLImageElement*>(curr)->useMap().substring(1) == map->getName())
- return axObjectCache()->get(obj);
+ return axObjectCache()->getOrCreate(obj);
}
return 0;
@@ -1496,7 +1545,7 @@ void AccessibilityRenderObject::getDocumentLinks(AccessibilityChildrenVector& re
while (curr) {
RenderObject* obj = curr->renderer();
if (obj) {
- RefPtr<AccessibilityObject> axobj = document->axObjectCache()->get(obj);
+ RefPtr<AccessibilityObject> axobj = document->axObjectCache()->getOrCreate(obj);
ASSERT(axobj);
ASSERT(axobj->roleValue() == WebCoreLinkRole);
if (!axobj->accessibilityIsIgnored())
@@ -1504,7 +1553,7 @@ void AccessibilityRenderObject::getDocumentLinks(AccessibilityChildrenVector& re
} else {
Node* parent = curr->parent();
if (parent && curr->hasTagName(areaTag) && parent->hasTagName(mapTag)) {
- AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->get(ImageMapLinkRole));
+ AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->getOrCreate(ImageMapLinkRole));
areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(curr));
areaObject->setHTMLMapElement(static_cast<HTMLMapElement*>(parent));
areaObject->setParent(accessibilityParentForImageMap(static_cast<HTMLMapElement*>(parent)));
@@ -1548,20 +1597,23 @@ VisiblePositionRange AccessibilityRenderObject::visiblePositionRange() const
return VisiblePositionRange();
// construct VisiblePositions for start and end
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
if (!node)
return VisiblePositionRange();
-
- VisiblePosition startPos = VisiblePosition(node, 0, VP_DEFAULT_AFFINITY);
- VisiblePosition endPos = VisiblePosition(node, maxDeepOffset(node), VP_DEFAULT_AFFINITY);
-
+
+ VisiblePosition startPos = firstDeepEditingPositionForNode(node);
+ VisiblePosition endPos = lastDeepEditingPositionForNode(node);
+
// the VisiblePositions are equal for nodes like buttons, so adjust for that
+ // FIXME: Really? [button, 0] and [button, 1] are distinct (before and after the button)
+ // I expect this code is only hit for things like empty divs? In which case I don't think
+ // the behavior is correct here -- eseidel
if (startPos == endPos) {
endPos = endPos.next();
if (endPos.isNull())
endPos = startPos;
}
-
+
return VisiblePositionRange(startPos, endPos);
}
@@ -1587,7 +1639,7 @@ VisiblePositionRange AccessibilityRenderObject::visiblePositionRangeForLine(unsi
// starting at an empty line. The resulting selection in that case
// will be a caret at visiblePos.
SelectionController selection;
- selection.setSelection(Selection(visiblePos));
+ selection.setSelection(VisibleSelection(visiblePos));
selection.modify(SelectionController::EXTEND, SelectionController::RIGHT, LineBoundary);
return VisiblePositionRange(selection.selection().visibleStart(), selection.selection().visibleEnd());
@@ -1599,7 +1651,7 @@ VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(int index) co
return VisiblePosition();
if (isNativeTextControl())
- return static_cast<RenderTextControl*>(m_renderer)->visiblePositionForIndex(index);
+ return toRenderTextControl(m_renderer)->visiblePositionForIndex(index);
if (!isTextControl() && !m_renderer->isText())
return VisiblePosition();
@@ -1622,7 +1674,7 @@ VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(int index) co
int AccessibilityRenderObject::indexForVisiblePosition(const VisiblePosition& pos) const
{
if (isNativeTextControl())
- return static_cast<RenderTextControl*>(m_renderer)->indexForVisiblePosition(pos);
+ return toRenderTextControl(m_renderer)->indexForVisiblePosition(pos);
if (!isTextControl())
return 0;
@@ -1638,7 +1690,7 @@ int AccessibilityRenderObject::indexForVisiblePosition(const VisiblePosition& po
ExceptionCode ec = 0;
RefPtr<Range> range = Range::create(m_renderer->document());
range->setStart(node, 0, ec);
- range->setEnd(indexPosition.node(), indexPosition.offset(), ec);
+ range->setEnd(indexPosition.node(), indexPosition.m_offset, ec);
return TextIterator::rangeLength(range.get());
}
@@ -1694,7 +1746,7 @@ void AccessibilityRenderObject::setSelectedVisiblePositionRange(const VisiblePos
m_renderer->document()->frame()->selection()->moveTo(range.start, true);
}
else {
- Selection newSelection = Selection(range.start, range.end);
+ VisibleSelection newSelection = VisibleSelection(range.start, range.end);
m_renderer->document()->frame()->selection()->setSelection(newSelection);
}
}
@@ -1715,7 +1767,8 @@ VisiblePosition AccessibilityRenderObject::visiblePositionForPoint(const IntPoin
#else
ourpoint = point;
#endif
- HitTestRequest request(true, true);
+ HitTestRequest request(HitTestRequest::ReadOnly |
+ HitTestRequest::Active);
HitTestResult result(ourpoint);
renderView->layer()->hitTest(request, result);
innerNode = result.innerNode();
@@ -1736,10 +1789,7 @@ VisiblePosition AccessibilityRenderObject::visiblePositionForPoint(const IntPoin
Frame* frame = static_cast<FrameView*>(widget)->frame();
if (!frame)
break;
- Document* document = frame->document();
- if (!document)
- break;
- renderView = document->renderView();
+ renderView = frame->document()->renderView();
frameView = static_cast<FrameView*>(widget);
}
@@ -1772,7 +1822,7 @@ int AccessibilityRenderObject::index(const VisiblePosition& position) const
if (!node)
return -1;
- for (RenderObject* renderer = node->renderer(); renderer && renderer->element(); renderer = renderer->parent()) {
+ for (RenderObject* renderer = node->renderer(); renderer && renderer->node(); renderer = renderer->parent()) {
if (renderer == m_renderer)
return indexForVisiblePosition(position);
}
@@ -1802,7 +1852,7 @@ PlainTextRange AccessibilityRenderObject::doAXRangeForLine(unsigned lineNumber)
// starting at an empty line. The resulting selection in that case
// will be a caret at visiblePos.
SelectionController selection;
- selection.setSelection(Selection(visiblePos));
+ selection.setSelection(VisibleSelection(visiblePos));
selection.modify(SelectionController::EXTEND, SelectionController::LEFT, LineBoundary);
selection.modify(SelectionController::EXTEND, SelectionController::RIGHT, LineBoundary);
@@ -1875,7 +1925,8 @@ AccessibilityObject* AccessibilityRenderObject::doAccessibilityHitTest(const Int
RenderLayer* layer = toRenderBox(m_renderer)->layer();
- HitTestRequest request(true, true);
+ HitTestRequest request(HitTestRequest::ReadOnly |
+ HitTestRequest::Active);
HitTestResult hitTestResult = HitTestResult(point);
layer->hitTest(request, hitTestResult);
if (!hitTestResult.innerNode())
@@ -1885,7 +1936,7 @@ AccessibilityObject* AccessibilityRenderObject::doAccessibilityHitTest(const Int
if (!obj)
return 0;
- AccessibilityObject *result = obj->document()->axObjectCache()->get(obj);
+ AccessibilityObject *result = obj->document()->axObjectCache()->getOrCreate(obj);
if (obj->isListBox())
return static_cast<AccessibilityListBox*>(result)->doAccessibilityHitTest(point);
@@ -1912,7 +1963,7 @@ AccessibilityObject* AccessibilityRenderObject::focusedUIElement() const
if (!focusedNodeRenderer)
return 0;
- AccessibilityObject* obj = focusedNodeRenderer->document()->axObjectCache()->get(focusedNodeRenderer);
+ AccessibilityObject* obj = focusedNodeRenderer->document()->axObjectCache()->getOrCreate(focusedNodeRenderer);
if (obj->shouldFocusActiveDescendant()) {
if (AccessibilityObject* descendant = obj->activeDescendant())
@@ -1957,9 +2008,9 @@ bool AccessibilityRenderObject::shouldFocusActiveDescendant() const
AccessibilityObject* AccessibilityRenderObject::activeDescendant() const
{
- if (renderer()->element() && !renderer()->element()->isElementNode())
+ if (renderer()->node() && !renderer()->node()->isElementNode())
return 0;
- Element* element = static_cast<Element*>(renderer()->element());
+ Element* element = static_cast<Element*>(renderer()->node());
String activeDescendantAttrStr = element->getAttribute(aria_activedescendantAttr).string();
if (activeDescendantAttrStr.isNull() || activeDescendantAttrStr.isEmpty())
@@ -1969,7 +2020,7 @@ AccessibilityObject* AccessibilityRenderObject::activeDescendant() const
if (!target)
return 0;
- AccessibilityObject* obj = renderer()->document()->axObjectCache()->get(target->renderer());
+ AccessibilityObject* obj = renderer()->document()->axObjectCache()->getOrCreate(target->renderer());
if (obj->isAccessibilityRenderObject())
// an activedescendant is only useful if it has a renderer, because that's what's needed to post the notification
return obj;
@@ -1979,7 +2030,7 @@ AccessibilityObject* AccessibilityRenderObject::activeDescendant() const
void AccessibilityRenderObject::handleActiveDescendantChanged()
{
- Element* element = static_cast<Element*>(renderer()->element());
+ Element* element = static_cast<Element*>(renderer()->node());
if (!element)
return;
Document* doc = renderer()->document();
@@ -1994,9 +2045,9 @@ void AccessibilityRenderObject::handleActiveDescendantChanged()
AccessibilityObject* AccessibilityRenderObject::observableObject() const
{
- for (RenderObject* renderer = m_renderer; renderer && renderer->element(); renderer = renderer->parent()) {
- if (renderer->isTextField() || renderer->isTextArea())
- return renderer->document()->axObjectCache()->get(renderer);
+ for (RenderObject* renderer = m_renderer; renderer && renderer->node(); renderer = renderer->parent()) {
+ if (renderer->isTextControl())
+ return renderer->document()->axObjectCache()->getOrCreate(renderer);
}
return 0;
@@ -2089,7 +2140,7 @@ AccessibilityRole AccessibilityRenderObject::roleValue() const
if (!m_renderer)
return UnknownRole;
- Node* node = m_renderer->element();
+ Node* node = m_renderer->node();
AccessibilityRole ariaRole = ariaRoleAttribute();
if (ariaRole != UnknownRole)
return ariaRole;
@@ -2138,7 +2189,7 @@ AccessibilityRole AccessibilityRenderObject::roleValue() const
if (m_renderer->isMenuList())
return PopUpButtonRole;
- if (headingLevel(m_renderer->element()) != 0)
+ if (headingLevel(m_renderer->node()) != 0)
return HeadingRole;
if (node && node->hasTagName(ddTag))
@@ -2178,12 +2229,18 @@ bool AccessibilityRenderObject::ariaRoleHasPresentationalChildren() const
bool AccessibilityRenderObject::canSetFocusAttribute() const
{
+ ASSERT(m_renderer);
+
// NOTE: It would be more accurate to ask the document whether setFocusedNode() would
// do anything. For example, it setFocusedNode() will do nothing if the current focused
// node will not relinquish the focus.
- if (!m_renderer->element() || !m_renderer->element()->isEnabled())
+ if (!m_renderer->node() || !m_renderer->node()->isElementNode())
return false;
-
+
+ FormControlElement* formControlElement = toFormControlElement(static_cast<Element*>(m_renderer->node()));
+ if (formControlElement && !formControlElement->isEnabled())
+ return false;
+
switch (roleValue()) {
case WebCoreLinkRole:
case ImageMapLinkRole:
@@ -2219,13 +2276,15 @@ void AccessibilityRenderObject::childrenChanged()
markChildrenDirty();
- // this object may not be accessible (and thus may not appear
+ // This object may not be accessible (and thus may not appear
// in the hierarchy), which means we need to go up the parent
// chain and mark the parent's dirty. Ideally, we would want
// to only access the next object that is not ignored, but
// asking an element if it's ignored can lead to an examination of the
- // render tree which is dangerous.
- for (AccessibilityObject* parent = parentObject(); parent; parent = parent->parentObject()) {
+ // render tree which is dangerous.
+ // Only parents that already exist must be retrieved, otherwise objects can be created
+ // at bad times
+ for (AccessibilityObject* parent = parentObjectIfExists(); parent; parent = parent->parentObjectIfExists()) {
if (parent->isAccessibilityRenderObject())
static_cast<AccessibilityRenderObject *>(parent)->markChildrenDirty();
}
@@ -2291,13 +2350,13 @@ void AccessibilityRenderObject::addChildren()
// for a RenderImage, add the <area> elements as individual accessibility objects
if (m_renderer->isRenderImage()) {
- HTMLMapElement* map = static_cast<RenderImage*>(m_renderer)->imageMap();
+ HTMLMapElement* map = toRenderImage(m_renderer)->imageMap();
if (map) {
for (Node* current = map->firstChild(); current; current = current->traverseNextNode(map)) {
// add an <area> element for this child if it has a link
if (current->isLink()) {
- AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(m_renderer->document()->axObjectCache()->get(ImageMapLinkRole));
+ AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(m_renderer->document()->axObjectCache()->getOrCreate(ImageMapLinkRole));
areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(current));
areaObject->setHTMLMapElement(map);
areaObject->setParent(this);
@@ -2314,7 +2373,7 @@ void AccessibilityRenderObject::ariaListboxSelectedChildren(AccessibilityChildre
AccessibilityObject* child = firstChild();
bool isMultiselectable = false;
- Element* element = static_cast<Element*>(renderer()->element());
+ Element* element = static_cast<Element*>(renderer()->node());
if (!element || !element->isElementNode()) // do this check to ensure safety of static_cast above
return;
@@ -2328,7 +2387,7 @@ void AccessibilityRenderObject::ariaListboxSelectedChildren(AccessibilityChildre
if (child->isAccessibilityRenderObject())
childRenderer = static_cast<AccessibilityRenderObject*>(child)->renderer();
if (childRenderer && ariaRole == ListBoxOptionRole) {
- Element* childElement = static_cast<Element*>(childRenderer->element());
+ Element* childElement = static_cast<Element*>(childRenderer->node());
if (childElement && childElement->isElementNode()) { // do this check to ensure safety of static_cast above
String selectedAttrString = childElement->getAttribute("aria-selected").string();
if (equalIgnoringCase(selectedAttrString, "true")) {
@@ -2378,15 +2437,6 @@ void AccessibilityRenderObject::visibleChildren(AccessibilityChildrenVector& res
return ariaListboxVisibleChildren(result);
}
-void AccessibilityRenderObject::removeAXObjectID()
-{
- if (!m_id)
- return;
-#if PLATFORM(MAC)
- m_renderer->document()->axObjectCache()->removeAXID(this);
-#endif
-}
-
const String& AccessibilityRenderObject::actionVerb() const
{
// FIXME: Need to add verbs for select elements.
diff --git a/WebCore/page/AccessibilityRenderObject.h b/WebCore/page/AccessibilityRenderObject.h
index 03ba1db..5370eac 100644
--- a/WebCore/page/AccessibilityRenderObject.h
+++ b/WebCore/page/AccessibilityRenderObject.h
@@ -51,7 +51,7 @@ class RenderObject;
class RenderListBox;
class RenderTextControl;
class RenderView;
-class Selection;
+class VisibleSelection;
class String;
class Widget;
@@ -125,6 +125,7 @@ public:
virtual AccessibilityObject* previousSibling() const;
virtual AccessibilityObject* nextSibling() const;
virtual AccessibilityObject* parentObject() const;
+ virtual AccessibilityObject* parentObjectIfExists() const;
virtual AccessibilityObject* observableObject() const;
virtual void linkedUIElements(AccessibilityChildrenVector&) const;
virtual AccessibilityObject* titleUIElement() const;
@@ -156,7 +157,7 @@ public:
virtual KURL url() const;
virtual PlainTextRange selectedTextRange() const;
- virtual Selection selection() const;
+ virtual VisibleSelection selection() const;
virtual String stringValue() const;
virtual String ariaAccessiblityName(const String&) const;
virtual String ariaLabeledByAttribute() const;
@@ -218,7 +219,6 @@ protected:
mutable bool m_childrenDirty;
void setRenderObject(RenderObject* renderer) { m_renderer = renderer; }
- virtual void removeAXObjectID();
virtual bool isDetached() const { return !m_renderer; }
diff --git a/WebCore/page/AccessibilityTable.cpp b/WebCore/page/AccessibilityTable.cpp
index 9409283..2b60d43 100644
--- a/WebCore/page/AccessibilityTable.cpp
+++ b/WebCore/page/AccessibilityTable.cpp
@@ -93,7 +93,7 @@ bool AccessibilityTable::isTableExposableThroughAccessibility()
// Unfortunately, there is no good way to determine the difference
// between a "layout" table and a "data" table
- Node* tableNode = table->element();
+ Node* tableNode = table->node();
if (!tableNode || !tableNode->hasTagName(tableTag))
return false;
@@ -139,7 +139,7 @@ bool AccessibilityTable::isTableExposableThroughAccessibility()
RenderTableCell* cell = firstBody->cellAt(row, col).cell;
if (!cell)
continue;
- Node* cellNode = cell->element();
+ Node* cellNode = cell->node();
if (!cellNode)
continue;
@@ -241,7 +241,7 @@ void AccessibilityTable::addChildren()
if (!cell)
continue;
- AccessibilityObject* rowObject = axCache->get(cell->parent());
+ AccessibilityObject* rowObject = axCache->getOrCreate(cell->parent());
if (!rowObject->isTableRow())
continue;
@@ -264,7 +264,7 @@ void AccessibilityTable::addChildren()
// make the columns based on the number of columns in the first body
unsigned length = initialTableSection->numColumns();
for (unsigned i = 0; i < length; ++i) {
- AccessibilityTableColumn* column = static_cast<AccessibilityTableColumn*>(axCache->get(ColumnRole));
+ AccessibilityTableColumn* column = static_cast<AccessibilityTableColumn*>(axCache->getOrCreate(ColumnRole));
column->setColumnIndex((int)i);
column->setParentTable(this);
m_columns.append(column);
@@ -281,7 +281,7 @@ AccessibilityObject* AccessibilityTable::headerContainer()
if (m_headerContainer)
return m_headerContainer;
- m_headerContainer = static_cast<AccessibilityTableHeaderContainer*>(axObjectCache()->get(TableHeaderContainerRole));
+ m_headerContainer = static_cast<AccessibilityTableHeaderContainer*>(axObjectCache()->getOrCreate(TableHeaderContainerRole));
m_headerContainer->setParentTable(this);
return m_headerContainer;
@@ -386,11 +386,13 @@ AccessibilityTableCell* AccessibilityTable::cellForColumnAndRow(unsigned column,
unsigned rowOffset = 0;
while (tableSection) {
- rowCount += tableSection->numRows();
+ unsigned numRows = tableSection->numRows();
unsigned numCols = tableSection->numColumns();
- if (row < rowCount && column < numCols) {
- int sectionSpecificRow = row - rowOffset;
+ rowCount += numRows;
+
+ unsigned sectionSpecificRow = row - rowOffset;
+ if (row < rowCount && column < numCols && sectionSpecificRow < numRows) {
cell = tableSection->cellAt(sectionSpecificRow, column).cell;
// we didn't find the cell, which means there's spanning happening
@@ -422,9 +424,9 @@ AccessibilityTableCell* AccessibilityTable::cellForColumnAndRow(unsigned column,
if (cell)
break;
- rowOffset += rowCount;
+ rowOffset += numRows;
// we didn't find anything between the rows we should have
- if (row < rowOffset)
+ if (row < rowCount)
break;
tableSection = table->sectionBelow(tableSection, true);
}
@@ -432,7 +434,7 @@ AccessibilityTableCell* AccessibilityTable::cellForColumnAndRow(unsigned column,
if (!cell)
return 0;
- AccessibilityObject* cellObject = axObjectCache()->get(cell);
+ AccessibilityObject* cellObject = axObjectCache()->getOrCreate(cell);
ASSERT(cellObject->isTableCell());
return static_cast<AccessibilityTableCell*>(cellObject);
@@ -464,7 +466,7 @@ String AccessibilityTable::title() const
return title;
// see if there is a caption
- Node *tableElement = m_renderer->element();
+ Node* tableElement = m_renderer->node();
if (tableElement) {
HTMLTableCaptionElement* caption = static_cast<HTMLTableElement*>(tableElement)->caption();
if (caption)
diff --git a/WebCore/page/AccessibilityTableCell.cpp b/WebCore/page/AccessibilityTableCell.cpp
index ff82811..f7cbe98 100644
--- a/WebCore/page/AccessibilityTableCell.cpp
+++ b/WebCore/page/AccessibilityTableCell.cpp
@@ -67,7 +67,7 @@ bool AccessibilityTableCell::isTableCell() const
if (!m_renderer)
return false;
- AccessibilityObject* renderTable = axObjectCache()->get(static_cast<RenderTableCell*>(m_renderer)->table());
+ AccessibilityObject* renderTable = axObjectCache()->getOrCreate(static_cast<RenderTableCell*>(m_renderer)->table());
if (!renderTable->isDataTable())
return false;
@@ -147,11 +147,11 @@ AccessibilityObject* AccessibilityTableCell::titleUIElement() const
if (!headerCell || headerCell == renderCell)
return 0;
- Node* cellElement = headerCell->element();
+ Node* cellElement = headerCell->node();
if (!cellElement || !cellElement->hasTagName(thTag))
return 0;
- return axObjectCache()->get(headerCell);
+ return axObjectCache()->getOrCreate(headerCell);
}
} // namespace WebCore
diff --git a/WebCore/page/AccessibilityTableColumn.cpp b/WebCore/page/AccessibilityTableColumn.cpp
index 6e03af9..ff330c0 100644
--- a/WebCore/page/AccessibilityTableColumn.cpp
+++ b/WebCore/page/AccessibilityTableColumn.cpp
@@ -124,7 +124,7 @@ AccessibilityObject* AccessibilityTableColumn::headerObjectForSection(RenderTabl
if ((testCell->col() + (testCell->colSpan()-1)) < m_columnIndex)
break;
- Node* node = testCell->element();
+ Node* node = testCell->node();
if (!node)
continue;
@@ -137,7 +137,7 @@ AccessibilityObject* AccessibilityTableColumn::headerObjectForSection(RenderTabl
if (!cell)
return 0;
- return m_parentTable->axObjectCache()->get(cell);
+ return m_parentTable->axObjectCache()->getOrCreate(cell);
}
void AccessibilityTableColumn::addChildren()
diff --git a/WebCore/page/AccessibilityTableRow.cpp b/WebCore/page/AccessibilityTableRow.cpp
index caccff5..e67fcfe 100644
--- a/WebCore/page/AccessibilityTableRow.cpp
+++ b/WebCore/page/AccessibilityTableRow.cpp
@@ -70,7 +70,7 @@ bool AccessibilityTableRow::isTableRow() const
if (!m_renderer)
return true;
- AccessibilityObject* renderTable = axObjectCache()->get(static_cast<RenderTableRow*>(m_renderer)->table());
+ AccessibilityObject* renderTable = axObjectCache()->getOrCreate(static_cast<RenderTableRow*>(m_renderer)->table());
if (!renderTable->isDataTable())
return false;
@@ -100,7 +100,7 @@ AccessibilityObject* AccessibilityTableRow::headerObject()
if (!cellRenderer)
return 0;
- Node* cellNode = cellRenderer->element();
+ Node* cellNode = cellRenderer->node();
if (!cellNode || !cellNode->hasTagName(thTag))
return 0;
diff --git a/WebCore/page/Chrome.cpp b/WebCore/page/Chrome.cpp
index 4698aa5..b37ebc4 100644
--- a/WebCore/page/Chrome.cpp
+++ b/WebCore/page/Chrome.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This library is free software; you can redistribute it and/or
@@ -28,6 +28,7 @@
#include "FloatRect.h"
#include "Frame.h"
#include "FrameTree.h"
+#include "Geolocation.h"
#include "HTMLFormElement.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
@@ -387,6 +388,16 @@ void Chrome::enableSuddenTermination()
m_client->enableSuddenTermination();
}
+void Chrome::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
+{
+ // Defer loads in case the client method runs a new event loop that would
+ // otherwise cause the load to continue while we're in the middle of executing JavaScript.
+ PageGroupLoadDeferrer deferrer(m_page, true);
+
+ ASSERT(frame);
+ m_client->requestGeolocationPermissionForFrame(frame, geolocation);
+}
+
void Chrome::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> fileChooser)
{
m_client->runOpenPanel(frame, fileChooser);
@@ -457,10 +468,8 @@ PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf)
m_deferredFrames.append(otherPage->mainFrame());
#if !PLATFORM(MAC)
- for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
- if (Document* document = frame->document())
- document->suspendActiveDOMObjects();
- }
+ for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext())
+ frame->document()->suspendActiveDOMObjects();
#endif
}
}
@@ -478,10 +487,8 @@ PageGroupLoadDeferrer::~PageGroupLoadDeferrer()
page->setDefersLoading(false);
#if !PLATFORM(MAC)
- for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
- if (Document* document = frame->document())
- document->resumeActiveDOMObjects();
- }
+ for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
+ frame->document()->resumeActiveDOMObjects();
#endif
}
}
diff --git a/WebCore/page/Chrome.h b/WebCore/page/Chrome.h
index 47b912d..ab0b42f 100644
--- a/WebCore/page/Chrome.h
+++ b/WebCore/page/Chrome.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -38,6 +38,7 @@ namespace WebCore {
class ContextMenu;
class FloatRect;
class Frame;
+ class Geolocation;
class HitTestResult;
class IntRect;
class Page;
@@ -119,6 +120,8 @@ namespace WebCore {
void enableSuddenTermination();
void disableSuddenTermination();
+ void requestGeolocationPermissionForFrame(Frame*, Geolocation*);
+
void runOpenPanel(Frame*, PassRefPtr<FileChooser>);
#if PLATFORM(MAC)
diff --git a/WebCore/page/ChromeClient.h b/WebCore/page/ChromeClient.h
index 5d90b2f..6f82bc1 100644
--- a/WebCore/page/ChromeClient.h
+++ b/WebCore/page/ChromeClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple, Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -42,16 +42,21 @@ namespace WebCore {
class FileChooser;
class FloatRect;
class Frame;
+ class Geolocation;
class HitTestResult;
class IntRect;
class Node;
class Page;
class String;
class Widget;
-
+
struct FrameLoadRequest;
struct WindowFeatures;
+#if USE(ACCELERATED_COMPOSITING)
+ class GraphicsLayer;
+#endif
+
class ChromeClient {
public:
virtual void chromeDestroyed() = 0;
@@ -148,12 +153,24 @@ namespace WebCore {
float value, float proportion, ScrollbarControlPartMask);
virtual bool paintCustomScrollCorner(GraphicsContext*, const FloatRect&);
+ // This is an asynchronous call. The ChromeClient can display UI asking the user for permission
+ // to use Geolococation. The ChromeClient must call Geolocation::setShouldClearCache() appropriately.
+ virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*) { }
+
virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>) = 0;
// Notification that the given form element has changed. This function
// will be called frequently, so handling should be very fast.
virtual void formStateDidChange(const Node*) = 0;
+#if USE(ACCELERATED_COMPOSITING)
+ // Pass 0 as the GraphicsLayer to detatch the root layer.
+ virtual void attachRootGraphicsLayer(Frame*, GraphicsLayer*) { }
+ // Sets a flag to specify that the next time content is drawn to the window,
+ // the changes appear on the screen in synchrony with updates to GraphicsLayers.
+ virtual void setNeedsOneShotDrawingSynchronization() { }
+#endif
+
#if PLATFORM(MAC)
virtual KeyboardUIMode keyboardUIMode() { return KeyboardAccessDefault; }
diff --git a/WebCore/page/Console.cpp b/WebCore/page/Console.cpp
index 8755f0e..33128ea 100644
--- a/WebCore/page/Console.cpp
+++ b/WebCore/page/Console.cpp
@@ -68,7 +68,7 @@ static void printSourceURLAndLine(const String& sourceURL, unsigned lineNumber)
}
}
-static bool getFirstArgumentAsString(const ScriptCallFrame& callFrame, String& result, bool checkForNullOrUndefined = false)
+static bool getFirstArgumentAsString(ScriptState* scriptState, const ScriptCallFrame& callFrame, String& result, bool checkForNullOrUndefined = false)
{
if (!callFrame.argumentCount())
return false;
@@ -77,7 +77,8 @@ static bool getFirstArgumentAsString(const ScriptCallFrame& callFrame, String& r
if (checkForNullOrUndefined && (value.isNull() || value.isUndefined()))
return false;
- return value.getString(result);
+ result = value.toString(scriptState);
+ return true;
}
static void printMessageSourceAndLevelPrefix(MessageSource source, MessageLevel level)
@@ -99,12 +100,13 @@ static void printMessageSourceAndLevelPrefix(MessageSource source, MessageLevel
case CSSMessageSource:
sourceString = "CSS";
break;
- default:
- ASSERT_NOT_REACHED();
- // Fall thru.
case OtherMessageSource:
sourceString = "OTHER";
break;
+ default:
+ ASSERT_NOT_REACHED();
+ sourceString = "UNKNOWN";
+ break;
}
const char* levelString;
@@ -112,9 +114,6 @@ static void printMessageSourceAndLevelPrefix(MessageSource source, MessageLevel
case TipMessageLevel:
levelString = "TIP";
break;
- default:
- ASSERT_NOT_REACHED();
- // Fall thru.
case LogMessageLevel:
levelString = "LOG";
break;
@@ -124,6 +123,22 @@ static void printMessageSourceAndLevelPrefix(MessageSource source, MessageLevel
case ErrorMessageLevel:
levelString = "ERROR";
break;
+ case ObjectMessageLevel:
+ levelString = "OBJECT";
+ break;
+ case TraceMessageLevel:
+ levelString = "TRACE";
+ break;
+ case StartGroupMessageLevel:
+ levelString = "START GROUP";
+ break;
+ case EndGroupMessageLevel:
+ levelString = "END GROUP";
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ levelString = "UNKNOWN";
+ break;
}
printf("%s %s:", sourceString, levelString);
@@ -160,7 +175,7 @@ void Console::addMessage(MessageLevel level, ScriptCallStack* callStack, bool ac
return;
String message;
- if (getFirstArgumentAsString(lastCaller, message))
+ if (getFirstArgumentAsString(callStack->state(), lastCaller, message))
page->chrome()->client()->addMessageToConsole(message, lastCaller.lineNumber(), lastCaller.sourceURL().prettyURL());
page->inspectorController()->addMessageToConsole(JSMessageSource, level, callStack);
@@ -207,7 +222,8 @@ void Console::dir(ScriptCallStack* callStack)
void Console::dirxml(ScriptCallStack* callStack)
{
- addMessage(NodeMessageLevel, callStack);
+ // The standard behavior of our console.log will print the DOM tree for nodes.
+ log(callStack);
}
void Console::trace(ScriptCallStack* callStack)
@@ -243,7 +259,7 @@ void Console::count(ScriptCallStack* callStack)
// Follow Firebug's behavior of counting with null and undefined title in
// the same bucket as no argument
String title;
- getFirstArgumentAsString(lastCaller, title);
+ getFirstArgumentAsString(callStack->state(), lastCaller, title);
page->inspectorController()->count(title, lastCaller.lineNumber(), lastCaller.sourceURL().string());
}
@@ -256,13 +272,15 @@ void Console::profile(const JSC::UString& title, ScriptCallStack* callStack)
if (!page)
return;
- if (title.isNull())
- return;
-
// FIXME: log a console message when profiling is disabled.
if (!page->inspectorController()->profilerEnabled())
return;
+ if (title.isNull()) { // no title so give it the next user initiated profile title.
+ page->inspectorController()->startUserInitiatedProfiling(0);
+ return;
+ }
+
JSC::Profiler::profiler()->startProfiling(callStack->state(), title);
}
diff --git a/WebCore/page/Console.h b/WebCore/page/Console.h
index 7301fc9..2a24a2a 100644
--- a/WebCore/page/Console.h
+++ b/WebCore/page/Console.h
@@ -64,8 +64,8 @@ namespace WebCore {
LogMessageLevel,
WarningMessageLevel,
ErrorMessageLevel,
+ // FIXME: the remaining levels should become a new MessageType enum.
ObjectMessageLevel,
- NodeMessageLevel,
TraceMessageLevel,
StartGroupMessageLevel,
EndGroupMessageLevel
diff --git a/WebCore/page/ContextMenuController.cpp b/WebCore/page/ContextMenuController.cpp
index 47a0663..522e939 100644
--- a/WebCore/page/ContextMenuController.cpp
+++ b/WebCore/page/ContextMenuController.cpp
@@ -83,15 +83,10 @@ void ContextMenuController::handleContextMenuEvent(Event* event)
if (!event->isMouseEvent())
return;
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
- IntPoint point = IntPoint(mouseEvent->pageX(), mouseEvent->pageY());
- HitTestResult result(point);
+ HitTestResult result(mouseEvent->absoluteLocation());
- if (Frame* frame = event->target()->toNode()->document()->frame()) {
- float zoomFactor = frame->pageZoomFactor();
- point.setX(static_cast<int>(point.x() * zoomFactor));
- point.setY(static_cast<int>(point.y() * zoomFactor));
- result = frame->eventHandler()->hitTestResultAtPoint(point, false);
- }
+ if (Frame* frame = event->target()->toNode()->document()->frame())
+ result = frame->eventHandler()->hitTestResultAtPoint(mouseEvent->absoluteLocation(), false);
if (!result.innerNonSharedNode())
return;
@@ -193,14 +188,14 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
#endif
case ContextMenuItemTagSpellingGuess:
ASSERT(frame->selectedText().length());
- if (frame->editor()->shouldInsertText(item->title(), frame->selection()->toRange().get(),
+ if (frame->editor()->shouldInsertText(item->title(), frame->selection()->toNormalizedRange().get(),
EditorInsertActionPasted)) {
Document* document = frame->document();
RefPtr<ReplaceSelectionCommand> command =
ReplaceSelectionCommand::create(document, createFragmentFromMarkup(document, item->title(), ""),
true, false, true);
applyCommand(command);
- frame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
+ frame->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
}
break;
case ContextMenuItemTagIgnoreSpelling:
@@ -238,7 +233,7 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
break;
case ContextMenuItemTagStartSpeaking: {
ExceptionCode ec;
- RefPtr<Range> selectedRange = frame->selection()->toRange();
+ RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
if (!selectedRange || selectedRange->collapsed(ec)) {
Document* document = result.innerNonSharedNode()->document();
selectedRange = document->createRange();
diff --git a/WebCore/page/Coordinates.cpp b/WebCore/page/Coordinates.cpp
new file mode 100644
index 0000000..637a8c2
--- /dev/null
+++ b/WebCore/page/Coordinates.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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.
+ */
+
+#include "config.h"
+#include "Coordinates.h"
+
+namespace WebCore {
+
+String Coordinates::toString() const
+{
+ return String::format("coordinate(%.6lg, %.6lg, %.6lg, %.6lg, %.6lg, %.6lg, %.6lg)",
+ m_latitude, m_longitude, m_altitude, m_accuracy,
+ m_altitudeAccuracy, m_heading, m_speed);
+}
+
+} // namespace WebCore
diff --git a/WebCore/page/Coordinates.h b/WebCore/page/Coordinates.h
new file mode 100644
index 0000000..743b04d
--- /dev/null
+++ b/WebCore/page/Coordinates.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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.
+ */
+
+#ifndef Coordinates_h
+#define Coordinates_h
+
+#include "Event.h"
+#include "PlatformString.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+typedef int ExceptionCode;
+
+class Coordinates : public RefCounted<Coordinates> {
+public:
+ static PassRefPtr<Coordinates> create(double latitude, double longitude, double altitude, double accuracy, double altitudeAccuracy, double heading, double speed) { return adoptRef(new Coordinates(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed)); }
+
+ double latitude() const { return m_latitude; }
+ double longitude() const { return m_longitude; }
+ double altitude() const { return m_altitude; }
+ double accuracy() const { return m_accuracy; }
+ double altitudeAccuracy() const { return m_altitudeAccuracy; }
+ double heading() const { return m_heading; }
+ double speed() const { return m_speed; }
+
+ String toString() const;
+
+private:
+ Coordinates(double latitude, double longitude, double altitude, double accuracy, double altitudeAccuracy, double heading, double speed)
+ : m_latitude(latitude)
+ , m_longitude(longitude)
+ , m_altitude(altitude)
+ , m_accuracy(accuracy)
+ , m_altitudeAccuracy(altitudeAccuracy)
+ , m_heading(heading)
+ , m_speed(speed)
+ {
+ }
+
+ double m_latitude;
+ double m_longitude;
+ double m_altitude;
+ double m_accuracy;
+ double m_altitudeAccuracy;
+ double m_heading;
+ double m_speed;
+};
+
+} // namespace WebCore
+
+#endif // Coordinates_h
diff --git a/WebCore/page/Coordinates.idl b/WebCore/page/Coordinates.idl
new file mode 100644
index 0000000..6318212
--- /dev/null
+++ b/WebCore/page/Coordinates.idl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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.
+ */
+
+module core {
+
+ interface Coordinates {
+ readonly attribute double latitude;
+ readonly attribute double longitude;
+ readonly attribute double altitude;
+ readonly attribute double accuracy;
+ readonly attribute double altitudeAccuracy;
+ readonly attribute double heading;
+ readonly attribute double speed;
+
+#if defined(LANGUAGE_JAVASCRIPT)
+ [DontEnum] DOMString toString();
+#endif
+ };
+}
diff --git a/WebCore/page/DOMSelection.cpp b/WebCore/page/DOMSelection.cpp
index 5dab325..86fe911 100644
--- a/WebCore/page/DOMSelection.cpp
+++ b/WebCore/page/DOMSelection.cpp
@@ -56,76 +56,89 @@ void DOMSelection::disconnectFrame()
m_frame = 0;
}
-Node* DOMSelection::anchorNode() const
+const VisibleSelection& DOMSelection::visibleSelection() const
{
- if (!m_frame)
- return 0;
+ ASSERT(m_frame);
+ return m_frame->selection()->selection();
+}
- const Selection& selection = m_frame->selection()->selection();
+static Position anchorPosition(const VisibleSelection& selection)
+{
Position anchor = selection.isBaseFirst() ? selection.start() : selection.end();
- anchor = rangeCompliantEquivalent(anchor);
- return anchor.node();
+ return rangeCompliantEquivalent(anchor);
}
-Node* DOMSelection::baseNode() const
+static Position focusPosition(const VisibleSelection& selection)
+{
+ Position focus = selection.isBaseFirst() ? selection.end() : selection.start();
+ return rangeCompliantEquivalent(focus);
+}
+
+static Position basePosition(const VisibleSelection& selection)
+{
+ return rangeCompliantEquivalent(selection.base());
+}
+
+static Position extentPosition(const VisibleSelection& selection)
+{
+ return rangeCompliantEquivalent(selection.extent());
+}
+
+Node* DOMSelection::anchorNode() const
{
if (!m_frame)
return 0;
- return rangeCompliantEquivalent(m_frame->selection()->selection().base()).node();
+ return anchorPosition(visibleSelection()).node();
}
int DOMSelection::anchorOffset() const
{
if (!m_frame)
return 0;
-
- const Selection& selection = m_frame->selection()->selection();
- Position anchor = selection.isBaseFirst() ? selection.start() : selection.end();
- anchor = rangeCompliantEquivalent(anchor);
- return anchor.offset();
+ return anchorPosition(visibleSelection()).m_offset;
}
-int DOMSelection::baseOffset() const
+Node* DOMSelection::focusNode() const
{
if (!m_frame)
return 0;
- return rangeCompliantEquivalent(m_frame->selection()->selection().base()).offset();
+ return focusPosition(visibleSelection()).node();
}
-Node* DOMSelection::focusNode() const
+int DOMSelection::focusOffset() const
{
if (!m_frame)
return 0;
-
- const Selection& selection = m_frame->selection()->selection();
- Position focus = selection.isBaseFirst() ? selection.end() : selection.start();
- focus = rangeCompliantEquivalent(focus);
- return focus.node();
+ return focusPosition(visibleSelection()).m_offset;
}
-Node* DOMSelection::extentNode() const
+Node* DOMSelection::baseNode() const
{
if (!m_frame)
return 0;
- return rangeCompliantEquivalent(m_frame->selection()->selection().extent()).node();
+ return basePosition(visibleSelection()).node();
}
-int DOMSelection::focusOffset() const
+int DOMSelection::baseOffset() const
{
if (!m_frame)
return 0;
+ return basePosition(visibleSelection()).m_offset;
+}
- const Selection& selection = m_frame->selection()->selection();
- Position focus = selection.isBaseFirst() ? selection.end() : selection.start();
- focus = rangeCompliantEquivalent(focus);
- return focus.offset();
+
+Node* DOMSelection::extentNode() const
+{
+ if (!m_frame)
+ return 0;
+ return extentPosition(visibleSelection()).node();
}
int DOMSelection::extentOffset() const
{
if (!m_frame)
return 0;
- return rangeCompliantEquivalent(m_frame->selection()->selection().extent()).offset();
+ return extentPosition(visibleSelection()).m_offset;
}
bool DOMSelection::isCollapsed() const
@@ -142,6 +155,9 @@ String DOMSelection::type() const
SelectionController* selection = m_frame->selection();
+ // This is a WebKit DOM extension, incompatible with an IE extension
+ // IE has this same attribute, but returns "none", "text" and "control"
+ // http://msdn.microsoft.com/en-us/library/ms534692(VS.85).aspx
if (selection->isNone())
return "None";
if (selection->isCaret())
@@ -173,7 +189,7 @@ void DOMSelection::collapseToEnd()
if (!m_frame)
return;
- const Selection& selection = m_frame->selection()->selection();
+ const VisibleSelection& selection = m_frame->selection()->selection();
m_frame->selection()->moveTo(VisiblePosition(selection.end(), DOWNSTREAM));
}
@@ -182,7 +198,7 @@ void DOMSelection::collapseToStart()
if (!m_frame)
return;
- const Selection& selection = m_frame->selection()->selection();
+ const VisibleSelection& selection = m_frame->selection()->selection();
m_frame->selection()->moveTo(VisiblePosition(selection.start(), DOWNSTREAM));
}
@@ -298,8 +314,11 @@ PassRefPtr<Range> DOMSelection::getRangeAt(int index, ExceptionCode& ec)
return 0;
}
- const Selection& selection = m_frame->selection()->selection();
- return selection.toRange();
+ // If you're hitting this, you've added broken multi-range selection support
+ ASSERT(rangeCount() == 1);
+
+ const VisibleSelection& selection = m_frame->selection()->selection();
+ return selection.firstRange();
}
void DOMSelection::removeAllRanges()
@@ -319,31 +338,31 @@ void DOMSelection::addRange(Range* r)
SelectionController* selection = m_frame->selection();
if (selection->isNone()) {
- selection->setSelection(Selection(r));
+ selection->setSelection(VisibleSelection(r));
return;
}
- RefPtr<Range> range = selection->selection().toRange();
+ RefPtr<Range> range = selection->selection().toNormalizedRange();
ExceptionCode ec = 0;
if (r->compareBoundaryPoints(Range::START_TO_START, range.get(), ec) == -1) {
// We don't support discontiguous selection. We don't do anything if r and range don't intersect.
if (r->compareBoundaryPoints(Range::START_TO_END, range.get(), ec) > -1) {
if (r->compareBoundaryPoints(Range::END_TO_END, range.get(), ec) == -1)
// The original range and r intersect.
- selection->setSelection(Selection(r->startPosition(), range->endPosition(), DOWNSTREAM));
+ selection->setSelection(VisibleSelection(r->startPosition(), range->endPosition(), DOWNSTREAM));
else
// r contains the original range.
- selection->setSelection(Selection(r));
+ selection->setSelection(VisibleSelection(r));
}
} else {
// We don't support discontiguous selection. We don't do anything if r and range don't intersect.
if (r->compareBoundaryPoints(Range::END_TO_START, range.get(), ec) < 1) {
if (r->compareBoundaryPoints(Range::END_TO_END, range.get(), ec) == -1)
// The original range contains r.
- selection->setSelection(Selection(range.get()));
+ selection->setSelection(VisibleSelection(range.get()));
else
// The original range and r intersect.
- selection->setSelection(Selection(range->startPosition(), r->endPosition(), DOWNSTREAM));
+ selection->setSelection(VisibleSelection(range->startPosition(), r->endPosition(), DOWNSTREAM));
}
}
}
@@ -361,7 +380,7 @@ void DOMSelection::deleteFromDocument()
if (isCollapsed())
selection->modify(SelectionController::EXTEND, SelectionController::BACKWARD, CharacterGranularity);
- RefPtr<Range> selectedRange = selection->selection().toRange();
+ RefPtr<Range> selectedRange = selection->selection().toNormalizedRange();
ExceptionCode ec = 0;
selectedRange->deleteContents(ec);
@@ -383,7 +402,7 @@ bool DOMSelection::containsNode(const Node* n, bool allowPartial) const
Node* parentNode = n->parentNode();
unsigned nodeIndex = n->nodeIndex();
- RefPtr<Range> selectedRange = selection->selection().toRange();
+ RefPtr<Range> selectedRange = selection->selection().toNormalizedRange();
if (!parentNode)
return false;
@@ -418,7 +437,7 @@ String DOMSelection::toString()
if (!m_frame)
return String();
- return plainText(m_frame->selection()->selection().toRange().get());
+ return plainText(m_frame->selection()->selection().toNormalizedRange().get());
}
} // namespace WebCore
diff --git a/WebCore/page/DOMSelection.h b/WebCore/page/DOMSelection.h
index fd8d1fc..6a914d6 100644
--- a/WebCore/page/DOMSelection.h
+++ b/WebCore/page/DOMSelection.h
@@ -40,6 +40,7 @@ namespace WebCore {
class Range;
class Node;
class String;
+ class VisibleSelection;
typedef int ExceptionCode;
@@ -88,12 +89,13 @@ namespace WebCore {
// Microsoft Selection Object API
void empty();
- //void clear();
- //TextRange *createRange();
private:
DOMSelection(Frame*);
-
+
+ // Convenience method for accessors, does not NULL check m_frame.
+ const VisibleSelection& visibleSelection() const;
+
Frame* m_frame;
};
diff --git a/WebCore/page/DOMSelection.idl b/WebCore/page/DOMSelection.idl
index 85d23bf..a54f9e4 100644
--- a/WebCore/page/DOMSelection.idl
+++ b/WebCore/page/DOMSelection.idl
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,35 +29,30 @@
module window {
+ // This is based off of Mozilla's Selection interface
+ // https://developer.mozilla.org/En/DOM/Selection
interface DOMSelection {
readonly attribute Node anchorNode;
readonly attribute long anchorOffset;
readonly attribute Node focusNode;
readonly attribute long focusOffset;
- readonly attribute Node baseNode;
- readonly attribute long baseOffset;
- readonly attribute Node extentNode;
- readonly attribute long extentOffset;
+
readonly attribute boolean isCollapsed;
- readonly attribute DOMString type;
readonly attribute long rangeCount;
void collapse(in Node node, in long index)
raises(DOMException);
void collapseToEnd();
void collapseToStart();
+
void deleteFromDocument();
boolean containsNode(in Node node, in boolean allowPartial);
void selectAllChildren(in Node node)
raises(DOMException);
- void empty();
- void setBaseAndExtent(in Node baseNode, in long baseOffset, in Node extentNode, in long extentOffset)
- raises(DOMException);
- void setPosition(in Node node, in long offset)
- raises(DOMException);
- void modify(in DOMString alter, in DOMString direction, in DOMString granularity);
+
void extend(in Node node, in long offset)
raises(DOMException);
+
Range getRangeAt(in long index)
raises(DOMException);
void removeAllRanges();
@@ -65,6 +61,26 @@ module window {
#if defined(LANGUAGE_JAVASCRIPT)
[DontEnum] DOMString toString();
#endif
+
+ // WebKit extensions
+ readonly attribute Node baseNode;
+ readonly attribute long baseOffset;
+ readonly attribute Node extentNode;
+ readonly attribute long extentOffset;
+
+ // WebKit's "type" accessor returns "None", "Range" and "Caret"
+ // IE's type accessor returns "none", "text" and "control"
+ readonly attribute DOMString type;
+
+ void modify(in DOMString alter, in DOMString direction, in DOMString granularity);
+ void setBaseAndExtent(in Node baseNode, in long baseOffset, in Node extentNode, in long extentOffset)
+ raises(DOMException);
+ void setPosition(in Node node, in long offset)
+ raises(DOMException);
+
+ // IE extentions
+ // http://msdn.microsoft.com/en-us/library/ms535869(VS.85).aspx
+ void empty();
};
}
diff --git a/WebCore/page/DOMTimer.cpp b/WebCore/page/DOMTimer.cpp
index 911da71..1cc7730 100644
--- a/WebCore/page/DOMTimer.cpp
+++ b/WebCore/page/DOMTimer.cpp
@@ -27,7 +27,6 @@
#include "config.h"
#include "DOMTimer.h"
-#include "Document.h"
#include "ScheduledAction.h"
#include "ScriptExecutionContext.h"
#include <wtf/HashSet.h>
@@ -39,7 +38,7 @@ namespace WebCore {
static const int maxTimerNestingLevel = 5;
static const double oneMillisecond = 0.001;
-static const double minTimerInterval = 0.010; // 10 milliseconds
+double DOMTimer::s_minTimerInterval = 0.010; // 10 milliseconds
static int timerNestingLevel = 0;
@@ -58,18 +57,15 @@ DOMTimer::DOMTimer(ScriptExecutionContext* context, ScheduledAction* action, int
m_nestingLevel = timerNestingLevel + 1;
- // FIXME: Move the timeout map and API to ScriptExecutionContext to be able
- // to create timeouts from Workers.
- ASSERT(scriptExecutionContext() && scriptExecutionContext()->isDocument());
- static_cast<Document*>(scriptExecutionContext())->addTimeout(m_timeoutId, this);
+ scriptExecutionContext()->addTimeout(m_timeoutId, this);
double intervalMilliseconds = max(oneMillisecond, timeout * oneMillisecond);
// Use a minimum interval of 10 ms to match other browsers, but only once we've
// nested enough to notice that we're repeating.
// Faster timers might be "better", but they're incompatible.
- if (intervalMilliseconds < minTimerInterval && m_nestingLevel >= maxTimerNestingLevel)
- intervalMilliseconds = minTimerInterval;
+ if (intervalMilliseconds < s_minTimerInterval && m_nestingLevel >= maxTimerNestingLevel)
+ intervalMilliseconds = s_minTimerInterval;
if (singleShot)
startOneShot(intervalMilliseconds);
else
@@ -79,8 +75,7 @@ DOMTimer::DOMTimer(ScriptExecutionContext* context, ScheduledAction* action, int
DOMTimer::~DOMTimer()
{
if (scriptExecutionContext()) {
- ASSERT(scriptExecutionContext()->isDocument());
- static_cast<Document*>(scriptExecutionContext())->removeTimeout(m_timeoutId);
+ scriptExecutionContext()->removeTimeout(m_timeoutId);
}
}
@@ -100,8 +95,7 @@ void DOMTimer::removeById(ScriptExecutionContext* context, int timeoutId)
// respectively
if (timeoutId <= 0)
return;
- ASSERT(context && context->isDocument());
- delete static_cast<Document*>(context)->findTimeout(timeoutId);
+ delete context->findTimeout(timeoutId);
}
void DOMTimer::fired()
@@ -111,10 +105,10 @@ void DOMTimer::fired()
// Simple case for non-one-shot timers.
if (isActive()) {
- if (repeatInterval() && repeatInterval() < minTimerInterval) {
+ if (repeatInterval() && repeatInterval() < s_minTimerInterval) {
m_nestingLevel++;
if (m_nestingLevel >= maxTimerNestingLevel)
- augmentRepeatInterval(minTimerInterval - repeatInterval());
+ augmentRepeatInterval(s_minTimerInterval - repeatInterval());
}
// No access to member variables after this point, it can delete the timer.
diff --git a/WebCore/page/DOMTimer.h b/WebCore/page/DOMTimer.h
index 200b9b1..f6343fc 100644
--- a/WebCore/page/DOMTimer.h
+++ b/WebCore/page/DOMTimer.h
@@ -51,6 +51,12 @@ public:
virtual void suspend();
virtual void resume();
+ // The lowest allowable timer setting (in seconds, 0.001 == 1 ms).
+ // Default is 10ms.
+ // Chromium uses a non-default timeout.
+ static double minTimerInterval() { return s_minTimerInterval; }
+ static void setMinTimerInterval(double value) { s_minTimerInterval = value; }
+
private:
DOMTimer(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot);
virtual void fired();
@@ -60,6 +66,7 @@ private:
OwnPtr<ScheduledAction> m_action;
double m_nextFireInterval;
double m_repeatInterval;
+ static double s_minTimerInterval;
};
} // namespace WebCore
diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp
index 70ee79e..f6fde05 100644
--- a/WebCore/page/DOMWindow.cpp
+++ b/WebCore/page/DOMWindow.cpp
@@ -46,6 +46,7 @@
#include "FrameView.h"
#include "HTMLFrameOwnerElement.h"
#include "History.h"
+#include "InspectorController.h"
#include "Location.h"
#include "MessageEvent.h"
#include "Navigator.h"
@@ -56,6 +57,7 @@
#include "Screen.h"
#include "SecurityOrigin.h"
#include "Settings.h"
+#include "WebKitPoint.h"
#include <algorithm>
#include <wtf/MathExtras.h>
@@ -323,10 +325,10 @@ Storage* DOMWindow::sessionStorage() const
return 0;
Document* document = m_frame->document();
- if (!document)
- return 0;
RefPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin());
+ page->inspectorController()->didUseDOMStorage(storageArea.get(), false, m_frame);
+
m_sessionStorage = Storage::create(m_frame, storageArea.release());
return m_sessionStorage.get();
}
@@ -347,8 +349,10 @@ Storage* DOMWindow::localStorage() const
LocalStorage* localStorage = page->group().localStorage();
RefPtr<StorageArea> storageArea = localStorage ? localStorage->storageArea(document->securityOrigin()) : 0;
- if (storageArea)
+ if (storageArea) {
+ page->inspectorController()->didUseDOMStorage(storageArea.get(), true, m_frame);
m_localStorage = Storage::create(m_frame, storageArea.release());
+ }
return m_localStorage.get();
}
@@ -449,7 +453,20 @@ void DOMWindow::close()
if (!m_frame)
return;
- if (m_frame->loader()->openedByDOM() || m_frame->loader()->getHistoryLength() <= 1)
+ Page* page = m_frame->page();
+ if (!page)
+ return;
+
+ if (m_frame != page->mainFrame())
+ return;
+
+ Settings* settings = m_frame->settings();
+ bool allowScriptsToCloseWindows =
+ settings && settings->allowScriptsToCloseWindows();
+
+ if (m_frame->loader()->openedByDOM()
+ || m_frame->loader()->getHistoryLength() <= 1
+ || allowScriptsToCloseWindows)
m_frame->scheduleClose();
}
@@ -480,10 +497,7 @@ void DOMWindow::alert(const String& message)
if (!m_frame)
return;
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateRendering();
+ m_frame->document()->updateRendering();
Page* page = m_frame->page();
if (!page)
@@ -497,10 +511,7 @@ bool DOMWindow::confirm(const String& message)
if (!m_frame)
return false;
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateRendering();
+ m_frame->document()->updateRendering();
Page* page = m_frame->page();
if (!page)
@@ -514,10 +525,7 @@ String DOMWindow::prompt(const String& message, const String& defaultValue)
if (!m_frame)
return String();
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateRendering();
+ m_frame->document()->updateRendering();
Page* page = m_frame->page();
if (!page)
@@ -625,10 +633,7 @@ int DOMWindow::scrollX() const
if (!view)
return 0;
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateLayoutIgnorePendingStylesheets();
+ m_frame->document()->updateLayoutIgnorePendingStylesheets();
return static_cast<int>(view->scrollX() / m_frame->pageZoomFactor());
}
@@ -649,10 +654,7 @@ int DOMWindow::scrollY() const
if (!view)
return 0;
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateLayoutIgnorePendingStylesheets();
+ m_frame->document()->updateLayoutIgnorePendingStylesheets();
return static_cast<int>(view->scrollY() / m_frame->pageZoomFactor());
}
@@ -786,15 +788,32 @@ PassRefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* elt, const String
return 0;
Document* doc = m_frame->document();
- ASSERT(doc);
- if (!doc)
- return 0;
if (!pseudoElt.isEmpty())
return doc->styleSelector()->pseudoStyleRulesForElement(elt, pseudoElt, authorOnly);
return doc->styleSelector()->styleRulesForElement(elt, authorOnly);
}
+PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromNodeToPage(Node* node, const WebKitPoint* p) const
+{
+ if (!node || !p)
+ return 0;
+
+ FloatPoint pagePoint(p->x(), p->y());
+ pagePoint = node->convertToPage(pagePoint);
+ return WebKitPoint::create(pagePoint.x(), pagePoint.y());
+}
+
+PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromPageToNode(Node* node, const WebKitPoint* p) const
+{
+ if (!node || !p)
+ return 0;
+
+ FloatPoint nodePoint(p->x(), p->y());
+ nodePoint = node->convertFromPage(nodePoint);
+ return WebKitPoint::create(nodePoint.x(), nodePoint.y());
+}
+
double DOMWindow::devicePixelRatio() const
{
if (!m_frame)
@@ -814,9 +833,6 @@ PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& v
return 0;
Document* doc = m_frame->document();
- ASSERT(doc);
- if (!doc)
- return 0;
Settings* settings = m_frame->settings();
if (!settings || !settings->databasesEnabled())
@@ -831,10 +847,7 @@ void DOMWindow::scrollBy(int x, int y) const
if (!m_frame)
return;
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateLayoutIgnorePendingStylesheets();
+ m_frame->document()->updateLayoutIgnorePendingStylesheets();
FrameView* view = m_frame->view();
if (!view)
@@ -848,10 +861,7 @@ void DOMWindow::scrollTo(int x, int y) const
if (!m_frame)
return;
- Document* doc = m_frame->document();
- ASSERT(doc);
- if (doc)
- doc->updateLayoutIgnorePendingStylesheets();
+ m_frame->document()->updateLayoutIgnorePendingStylesheets();
FrameView* view = m_frame->view();
if (!view)
diff --git a/WebCore/page/DOMWindow.h b/WebCore/page/DOMWindow.h
index da84e35..b779cbd 100644
--- a/WebCore/page/DOMWindow.h
+++ b/WebCore/page/DOMWindow.h
@@ -52,6 +52,8 @@ namespace WebCore {
class Navigator;
class PostMessageTimer;
class Screen;
+ class WebKitPoint;
+ class Node;
#if ENABLE(DOM_STORAGE)
class SessionStorage;
@@ -163,6 +165,9 @@ namespace WebCore {
PassRefPtr<CSSRuleList> getMatchedCSSRules(Element*, const String& pseudoElt, bool authorOnly = true) const;
double devicePixelRatio() const;
+ PassRefPtr<WebKitPoint> webkitConvertPointFromPageToNode(Node* node, const WebKitPoint* p) const;
+ PassRefPtr<WebKitPoint> webkitConvertPointFromNodeToPage(Node* node, const WebKitPoint* p) const;
+
#if ENABLE(DATABASE)
// HTML 5 client-side database
PassRefPtr<Database> openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, ExceptionCode&);
diff --git a/WebCore/page/DOMWindow.idl b/WebCore/page/DOMWindow.idl
index 78c780f..6bb08a8 100644
--- a/WebCore/page/DOMWindow.idl
+++ b/WebCore/page/DOMWindow.idl
@@ -53,7 +53,7 @@ module window {
attribute [Replaceable] BarInfo toolbar;
attribute [Replaceable] Navigator navigator;
attribute [Replaceable] Navigator clientInformation;
- attribute [DoNotCheckDomainSecurity, CustomSetter] Location location;
+ attribute [DoNotCheckDomainSecurity, CustomSetter, V8DisallowShadowing] Location location;
DOMSelection getSelection();
@@ -120,12 +120,12 @@ module window {
// Self referential attributes
attribute [Replaceable, DoNotCheckDomainSecurityOnGet] DOMWindow self;
- readonly attribute [DoNotCheckDomainSecurity] DOMWindow window;
+ readonly attribute [DoNotCheckDomainSecurity, V8DisallowShadowing] DOMWindow window;
attribute [Replaceable, DoNotCheckDomainSecurityOnGet] DOMWindow frames;
- attribute [Replaceable, DoNotCheckDomainSecurityOnGet] DOMWindow opener;
+ attribute [Replaceable, DoNotCheckDomainSecurityOnGet, V8CustomSetter] DOMWindow opener;
attribute [Replaceable, DoNotCheckDomainSecurity] DOMWindow parent;
- attribute [Replaceable, DoNotCheckDomainSecurity] DOMWindow top;
+ attribute [Replaceable, DoNotCheckDomainSecurity, V8DisallowShadowing, V8ReadOnly] DOMWindow top;
// DOM Level 2 AbstractView Interface
readonly attribute Document document;
@@ -139,6 +139,9 @@ module window {
in DOMString pseudoElement,
in [Optional] boolean authorOnly);
attribute [Replaceable] double devicePixelRatio;
+
+ WebKitPoint webkitConvertPointFromPageToNode(in Node node, in WebKitPoint p);
+ WebKitPoint webkitConvertPointFromNodeToPage(in Node node, in WebKitPoint p);
#if ENABLE_OFFLINE_WEB_APPLICATIONS
readonly attribute DOMApplicationCache applicationCache;
@@ -210,12 +213,17 @@ module window {
attribute [ProtectedListener] EventListener ontouchcancel;
#endif
+#if defined(V8_BINDING)
+ attribute [ProtectedListener] EventListener ondragdrop;
+ attribute [ProtectedListener] EventListener onmove;
+#endif
+
// EventTarget interface
- [Custom] void addEventListener(in DOMString type,
- in EventListener listener,
+ [Custom] void addEventListener(in DOMString type,
+ in EventListener listener,
in boolean useCapture);
- [Custom] void removeEventListener(in DOMString type,
- in EventListener listener,
+ [Custom] void removeEventListener(in DOMString type,
+ in EventListener listener,
in boolean useCapture);
// FIXME: Implement dispatchEvent
@@ -384,6 +392,17 @@ module window {
attribute XMLHttpRequestUploadConstructor XMLHttpRequestUpload;
attribute XMLHttpRequestExceptionConstructor XMLHttpRequestException;
+#if defined(V8_BINDING)
+ // With JSC, these are added in JSDOMWindowBase.cpp.
+ attribute XMLHttpRequestConstructor XMLHttpRequest;
+ attribute XSLTProcessorConstructor XSLTProcessor;
+ attribute MessageChannelConstructor MessageChannel;
+ attribute WebKitPointConstructor WebKitPoint;
+#if ENABLE_WORKERS
+ attribute WorkerConstructor Worker;
+#endif
+ attribute WebKitCSSMatrixConstructor WebKitCSSMatrix;
+#endif // V8_BINDING
attribute PluginConstructor Plugin;
attribute PluginArrayConstructor PluginArray;
@@ -391,6 +410,9 @@ module window {
attribute MimeTypeConstructor MimeType;
attribute MimeTypeArrayConstructor MimeTypeArray;
+ attribute ClientRectConstructor ClientRect;
+ attribute ClientRectListConstructor ClientRectList;
+
#if ENABLE_DOM_STORAGE
attribute StorageConstructor Storage;
attribute StorageEventConstructor StorageEvent;
@@ -440,6 +462,26 @@ module window {
#endif
#endif // defined(LANGUAGE_JAVASCRIPT)
- };
+#if defined(V8_BINDING)
+ // These were implemented in JSCDOMWindowBase and not moved to IDL yet.
+
+ [Custom] DOMWindow open(in DOMString url,
+ in DOMString name,
+ in [Optional] DOMString options);
+
+ [Custom] DOMObject showModalDialog(in DOMString url,
+ in [Optional] DOMObject dialogArgs,
+ in [Optional] DOMString featureArgs);
+
+ // These are defined on JSDOMWindowBase, but not implemented.
+ [Custom=DOMWindowNOP] void captureEvents(in long eventFlags);
+ [Custom=DOMWindowNOP] void releaseEvents(in long eventFlags);
+
+ // window.toString requires special handling
+ [V8DoNotCheckSignature, DoNotCheckDomainSecurity, Custom, DontEnum] DOMString toString();
+#endif // defined(V8_BINDING)
+ };
}
+
+
diff --git a/WebCore/page/DragController.cpp b/WebCore/page/DragController.cpp
index 9911f34..cba109a 100644
--- a/WebCore/page/DragController.cpp
+++ b/WebCore/page/DragController.cpp
@@ -107,9 +107,9 @@ static PassRefPtr<DocumentFragment> documentFragmentFromDragData(DragData* dragD
String title;
String url = dragData->asURL(&title);
if (!url.isEmpty()) {
- ExceptionCode ec;
- RefPtr<HTMLAnchorElement> anchor = static_cast<HTMLAnchorElement*>(document->createElement("a", ec).get());
+ RefPtr<HTMLAnchorElement> anchor = new HTMLAnchorElement(document);
anchor->setHref(url);
+ ExceptionCode ec;
RefPtr<Node> anchorText = document->createTextNode(title);
anchor->appendChild(anchorText, ec);
RefPtr<DocumentFragment> fragment = document->createDocumentFragment();
@@ -280,7 +280,7 @@ DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinatio
Frame* innerFrame = element->document()->frame();
ASSERT(innerFrame);
if (!asFileInput(element)) {
- Selection dragCaret;
+ VisibleSelection dragCaret;
if (Frame* frame = m_document->frame())
dragCaret = frame->visiblePositionForPoint(point);
m_page->dragCaretController()->setSelection(dragCaret);
@@ -309,13 +309,13 @@ DragOperation DragController::operationForLoad(DragData* dragData)
return dragOperation(dragData);
}
-static bool setSelectionToDragCaret(Frame* frame, Selection& dragCaret, RefPtr<Range>& range, const IntPoint& point)
+static bool setSelectionToDragCaret(Frame* frame, VisibleSelection& dragCaret, RefPtr<Range>& range, const IntPoint& point)
{
frame->selection()->setSelection(dragCaret);
if (frame->selection()->isNone()) {
dragCaret = frame->visiblePositionForPoint(point);
frame->selection()->setSelection(dragCaret);
- range = dragCaret.toRange();
+ range = dragCaret.toNormalizedRange();
}
return !frame->selection()->isNone() && frame->selection()->isContentEditable();
}
@@ -340,7 +340,7 @@ bool DragController::concludeEditDrag(DragData* dragData)
return false;
if (!innerFrame)
return false;
- RefPtr<Range> innerRange = innerFrame->selection()->toRange();
+ RefPtr<Range> innerRange = innerFrame->selection()->toNormalizedRange();
RefPtr<CSSStyleDeclaration> style = m_document->createCSSStyleDeclaration();
ExceptionCode ec;
style->setProperty("color", color.name(), ec);
@@ -381,9 +381,9 @@ bool DragController::concludeEditDrag(DragData* dragData)
return true;
}
- Selection dragCaret(m_page->dragCaretController()->selection());
+ VisibleSelection dragCaret(m_page->dragCaretController()->selection());
m_page->dragCaretController()->clear();
- RefPtr<Range> range = dragCaret.toRange();
+ RefPtr<Range> range = dragCaret.toNormalizedRange();
// For range to be null a WebKit client must have done something bad while
// manually controlling drag behaviour
@@ -531,7 +531,7 @@ static CachedImage* getCachedImage(Element* element)
RenderObject* renderer = element->renderer();
if (!renderer || !renderer->isImage())
return 0;
- RenderImage* image = static_cast<RenderImage*>(renderer);
+ RenderImage* image = toRenderImage(renderer);
return image->cachedImage();
}
@@ -542,7 +542,7 @@ static Image* getImage(Element* element)
if (!renderer || !renderer->isImage())
return 0;
- RenderImage* image = static_cast<RenderImage*>(renderer);
+ RenderImage* image = toRenderImage(renderer);
if (image->cachedImage() && !image->cachedImage()->errorOccurred())
return image->cachedImage()->image();
return 0;
@@ -554,7 +554,7 @@ static void prepareClipboardForImageDrag(Frame* src, Clipboard* clipboard, Eleme
ExceptionCode ec = 0;
range->selectNode(node, ec);
ASSERT(ec == 0);
- src->selection()->setSelection(Selection(range.get(), DOWNSTREAM));
+ src->selection()->setSelection(VisibleSelection(range.get(), DOWNSTREAM));
clipboard->declareAndWriteDragImage(node, !linkURL.isEmpty() ? linkURL : imageURL, label, src);
}
@@ -661,7 +661,7 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s
Position pos = src->selection()->base();
Node* node = enclosingAnchorElement(pos);
if (node)
- src->selection()->setSelection(Selection::selectionFromContentsOfNode(node));
+ src->selection()->setSelection(VisibleSelection::selectionFromContentsOfNode(node));
}
m_client->willPerformDragSourceAction(DragSourceActionLink, dragOrigin, clipboard);
@@ -673,7 +673,7 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s
}
doSystemDrag(dragImage, dragLoc, mouseDraggedPoint, clipboard, src, true);
} else if (isSelected && (m_dragSourceAction & DragSourceActionSelection)) {
- RefPtr<Range> selectionRange = src->selection()->toRange();
+ RefPtr<Range> selectionRange = src->selection()->toNormalizedRange();
ASSERT(selectionRange);
if (!clipboard->hasData())
clipboard->writeRange(selectionRange.get(), src);
@@ -771,7 +771,7 @@ void DragController::placeDragCaret(const IntPoint& windowPoint)
if (!frameView)
return;
IntPoint framePoint = frameView->windowToContents(windowPoint);
- Selection dragCaret(frame->visiblePositionForPoint(framePoint));
+ VisibleSelection dragCaret(frame->visiblePositionForPoint(framePoint));
m_page->dragCaretController()->setSelection(dragCaret);
}
diff --git a/WebCore/page/EditorClient.h b/WebCore/page/EditorClient.h
index 56d0435..67462c5 100644
--- a/WebCore/page/EditorClient.h
+++ b/WebCore/page/EditorClient.h
@@ -50,7 +50,7 @@ class HTMLElement;
class KeyboardEvent;
class Node;
class Range;
-class Selection;
+class VisibleSelection;
class String;
class VisiblePosition;
@@ -61,6 +61,13 @@ struct GrammarDetail {
String userDescription;
};
+struct TextCheckingResult {
+ int resultType; // 1 for spelling, 2 for grammar
+ int location;
+ int length;
+ Vector<GrammarDetail> details;
+};
+
class EditorClient {
public:
virtual ~EditorClient() { }
@@ -130,6 +137,9 @@ public:
virtual void learnWord(const String&) = 0;
virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength) = 0;
virtual void checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength) = 0;
+#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ virtual void checkSpellingAndGrammarOfParagraph(const UChar* text, int length, bool checkGrammar, Vector<TextCheckingResult>& results) = 0;
+#endif
virtual void updateSpellingUIWithGrammarString(const String&, const GrammarDetail& detail) = 0;
virtual void updateSpellingUIWithMisspelledWord(const String&) = 0;
virtual void showSpellingUI(bool show) = 0;
diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp
index 8cb46b7..7e79792 100644
--- a/WebCore/page/EventHandler.cpp
+++ b/WebCore/page/EventHandler.cpp
@@ -57,6 +57,7 @@
#include "PlatformKeyboardEvent.h"
#include "PlatformWheelEvent.h"
#include "RenderFrameSet.h"
+#include "RenderTextControlSingleLine.h"
#include "RenderWidget.h"
#include "RenderView.h"
#include "Scrollbar.h"
@@ -117,8 +118,6 @@ static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDir
return;
}
float pixelsToScroll = delta > 0 ? delta : -delta;
- if (e.granularity() == ScrollByLineWheelEvent)
- pixelsToScroll *= cMouseWheelPixelsPerLineStep;
if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll))
e.accept();
}
@@ -126,6 +125,7 @@ static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDir
EventHandler::EventHandler(Frame* frame)
: m_frame(frame)
, m_mousePressed(false)
+ , m_capturesDragging(false)
, m_mouseDownMayStartSelect(false)
, m_mouseDownMayStartDrag(false)
, m_mouseDownWasSingleClickInSelection(false)
@@ -186,18 +186,19 @@ void EventHandler::clear()
m_currentMousePosition = IntPoint();
m_mousePressNode = 0;
m_mousePressed = false;
+ m_capturesDragging = false;
m_capturingMouseEventsNode = 0;
}
void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result)
{
Node* innerNode = result.targetNode();
- Selection newSelection;
+ VisibleSelection newSelection;
if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
if (pos.isNotNull()) {
- newSelection = Selection(pos);
+ newSelection = VisibleSelection(pos);
newSelection.expandUsingGranularity(WordGranularity);
}
@@ -221,11 +222,11 @@ void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHit
Node* innerNode = result.targetNode();
if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
- Selection newSelection;
+ VisibleSelection newSelection;
Element* URLElement = result.hitTestResult().URLElement();
VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));
if (pos.isNotNull() && pos.deepEquivalent().node()->isDescendantOf(URLElement))
- newSelection = Selection::selectionFromContentsOfNode(URLElement);
+ newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement);
if (newSelection.isRange()) {
m_frame->setSelectionGranularity(WordGranularity);
@@ -264,10 +265,10 @@ bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR
if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
return false;
- Selection newSelection;
+ VisibleSelection newSelection;
VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint()));
if (pos.isNotNull()) {
- newSelection = Selection(pos);
+ newSelection = VisibleSelection(pos);
newSelection.expandUsingGranularity(ParagraphGranularity);
}
if (newSelection.isRange()) {
@@ -283,9 +284,6 @@ bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR
bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event)
{
- if (event.event().button() != LeftButton)
- return false;
-
Node* innerNode = event.targetNode();
if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
return false;
@@ -306,7 +304,7 @@ bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR
visiblePos = VisiblePosition(innerNode, 0, DOWNSTREAM);
Position pos = visiblePos.deepEquivalent();
- Selection newSelection = m_frame->selection()->selection();
+ VisibleSelection newSelection = m_frame->selection()->selection();
if (extendSelection && newSelection.isCaretOrRange()) {
m_frame->selection()->setLastChangeWasHorizontalExtension(false);
@@ -314,17 +312,17 @@ bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR
// was created right-to-left
Position start = newSelection.start();
Position end = newSelection.end();
- short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());
+ short before = Range::compareBoundaryPoints(pos.node(), pos.m_offset, start.node(), start.m_offset);
if (before <= 0)
- newSelection = Selection(pos, end);
+ newSelection = VisibleSelection(pos, end);
else
- newSelection = Selection(start, pos);
+ newSelection = VisibleSelection(start, pos);
if (m_frame->selectionGranularity() != CharacterGranularity)
newSelection.expandUsingGranularity(m_frame->selectionGranularity());
m_beganSelectingText = true;
} else {
- newSelection = Selection(visiblePos);
+ newSelection = VisibleSelection(visiblePos);
m_frame->setSelectionGranularity(CharacterGranularity);
}
@@ -375,18 +373,16 @@ bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve
m_dragStartPos = event.event().pos();
bool swallowEvent = false;
- if (event.event().button() == LeftButton || event.event().button() == MiddleButton) {
- m_frame->selection()->setCaretBlinkingSuspended(true);
- m_mousePressed = true;
- m_beganSelectingText = false;
-
- if (event.event().clickCount() == 2)
- swallowEvent = handleMousePressEventDoubleClick(event);
- else if (event.event().clickCount() >= 3)
- swallowEvent = handleMousePressEventTripleClick(event);
- else
- swallowEvent = handleMousePressEventSingleClick(event);
- }
+ m_frame->selection()->setCaretBlinkingSuspended(true);
+ m_mousePressed = true;
+ m_beganSelectingText = false;
+
+ if (event.event().clickCount() == 2)
+ swallowEvent = handleMousePressEventDoubleClick(event);
+ else if (event.event().clickCount() >= 3)
+ swallowEvent = handleMousePressEventTripleClick(event);
+ else
+ swallowEvent = handleMousePressEventSingleClick(event);
m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect ||
(m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNode->renderBox()->canBeProgramaticallyScrolled(true));
@@ -451,7 +447,7 @@ bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
if (!DHTMLFlag && !UAFlag)
return false;
- HitTestRequest request(true, false);
+ HitTestRequest request(HitTestRequest::ReadOnly);
HitTestResult result(m_frame->view()->windowToContents(event.pos()));
m_frame->contentRenderer()->layer()->hitTest(request, result);
bool srcIsDHTML;
@@ -470,8 +466,11 @@ void EventHandler::updateSelectionForMouseDrag()
if (!layer)
return;
+ HitTestRequest request(HitTestRequest::ReadOnly |
+ HitTestRequest::Active |
+ HitTestRequest::MouseMove);
HitTestResult result(view->windowToContents(m_currentMousePosition));
- layer->hitTest(HitTestRequest(true, true, true), result);
+ layer->hitTest(request, result);
updateSelectionForMouseDrag(result.innerNode(), result.localPoint());
}
@@ -498,7 +497,7 @@ void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint&
// Restart the selection if this is the first mouse move. This work is usually
// done in handleMousePressEvent, but not if the mouse press was on an existing selection.
- Selection newSelection = m_frame->selection()->selection();
+ VisibleSelection newSelection = m_frame->selection()->selection();
#if ENABLE(SVG)
// Special case to limit selection to the containing block for SVG text.
@@ -512,7 +511,7 @@ void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint&
if (!m_beganSelectingText) {
m_beganSelectingText = true;
- newSelection = Selection(targetPosition);
+ newSelection = VisibleSelection(targetPosition);
}
newSelection.setExtent(targetPosition);
@@ -550,6 +549,7 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
// the mouse is pressed again.
m_frame->selection()->setCaretBlinkingSuspended(false);
m_mousePressed = false;
+ m_capturesDragging = false;
m_mouseDownMayStartDrag = false;
m_mouseDownMayStartSelect = false;
m_mouseDownMayStartAutoscroll = false;
@@ -563,11 +563,11 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e
if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText
&& m_dragStartPos == event.event().pos()
&& m_frame->selection()->isRange()) {
- Selection newSelection;
+ VisibleSelection newSelection;
Node *node = event.targetNode();
if (node && node->isContentEditable() && node->renderer()) {
VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint());
- newSelection = Selection(pos);
+ newSelection = VisibleSelection(pos);
}
if (m_frame->shouldChangeSelection(newSelection))
m_frame->selection()->setSelection(newSelection);
@@ -630,6 +630,7 @@ void EventHandler::autoscrollTimerFired(Timer<EventHandler>*)
}
}
+#if ENABLE(PAN_SCROLLING)
void EventHandler::setPanScrollCursor()
{
// At the original click location we draw a 4 arrowed icon. Over this icon there won't be any scroll
@@ -661,6 +662,7 @@ void EventHandler::setPanScrollCursor()
else
m_frame->view()->setCursor(middlePanningCursor());
}
+#endif // ENABLE(PAN_SCROLLING)
RenderObject* EventHandler::autoscrollRenderer() const
{
@@ -688,7 +690,7 @@ void EventHandler::setAutoscrollRenderer(RenderObject* renderer)
void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
{
- if (!m_frame || !m_frame->document()) {
+ if (!m_frame) {
flagDHTML = false;
flagUA = false;
return;
@@ -699,12 +701,15 @@ void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection));
}
-HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent)
+HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool allowShadowContent, bool ignoreClipping)
{
HitTestResult result(point);
if (!m_frame->contentRenderer())
return result;
- m_frame->contentRenderer()->layer()->hitTest(HitTestRequest(true, true), result);
+ int hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
+ if (ignoreClipping)
+ hitType |= HitTestRequest::IgnoreClipping;
+ m_frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), result);
while (true) {
Node* n = result.innerNode();
@@ -721,7 +726,7 @@ HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool all
IntPoint widgetPoint(result.localPoint().x() + view->scrollX() - renderWidget->borderLeft() - renderWidget->paddingLeft(),
result.localPoint().y() + view->scrollY() - renderWidget->borderTop() - renderWidget->paddingTop());
HitTestResult widgetHitTestResult(widgetPoint);
- frame->contentRenderer()->layer()->hitTest(HitTestRequest(true, true), widgetHitTestResult);
+ frame->contentRenderer()->layer()->hitTest(HitTestRequest(hitType), widgetHitTestResult);
result = widgetHitTestResult;
}
@@ -732,7 +737,7 @@ HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool all
if (m_frame != mainFrame && resultFrame && resultFrame != mainFrame && !resultFrame->editor()->insideVisibleArea(result.point())) {
IntPoint windowPoint = resultFrame->view()->contentsToWindow(result.point());
IntPoint mainFramePoint = mainFrame->view()->windowToContents(windowPoint);
- result = mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, allowShadowContent);
+ result = mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, allowShadowContent, ignoreClipping);
}
if (!allowShadowContent)
@@ -791,9 +796,6 @@ void EventHandler::setMousePressNode(PassRefPtr<Node> node)
bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity granularity)
{
- if (!m_frame->document())
- return false;
-
Node* node = m_frame->document()->focusedNode();
if (!node)
node = m_mousePressNode.get();
@@ -1002,12 +1004,10 @@ Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scr
bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
{
- if (!m_frame->document())
- return false;
-
RefPtr<FrameView> protector(m_frame->view());
m_mousePressed = true;
+ m_capturesDragging = true;
m_currentMousePosition = mouseEvent.pos();
m_mouseDownTimestamp = mouseEvent.timestamp();
m_mouseDownMayStartDrag = false;
@@ -1016,7 +1016,8 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
m_mouseDownPos = m_frame->view()->windowToContents(mouseEvent.pos());
m_mouseDownWasInSubframe = false;
- MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, true), mouseEvent);
+ HitTestRequest request(HitTestRequest::Active);
+ MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
if (!mev.targetNode()) {
invalidateClick();
@@ -1036,7 +1037,8 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
if (subframe && passMousePressEventToSubframe(mev, subframe)) {
// Start capturing future events for this frame. We only do this if we didn't clear
// the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop.
- if (m_mousePressed)
+ m_capturesDragging = subframe->eventHandler()->capturesDragging();
+ if (m_mousePressed && m_capturesDragging)
m_capturingMouseEventsNode = mev.targetNode();
invalidateClick();
return true;
@@ -1082,12 +1084,15 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
}
bool swallowEvent = dispatchMouseEvent(eventNames().mousedownEvent, mev.targetNode(), true, m_clickCount, mouseEvent, true);
+ m_capturesDragging = !swallowEvent;
// If the hit testing originally determined the event was in a scrollbar, refetch the MouseEventWithHitTestResults
// in case the scrollbar widget was destroyed when the mouse event was handled.
if (mev.scrollbar()) {
const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMouse.get();
- mev = prepareMouseEvent(HitTestRequest(true, true), mouseEvent);
+ HitTestRequest request(HitTestRequest::ReadOnly |
+ HitTestRequest::Active);
+ mev = prepareMouseEvent(request, mouseEvent);
if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get())
m_lastScrollbarUnderMouse = 0;
@@ -1102,8 +1107,11 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
// If a mouse event handler changes the input element type to one that has a widget associated,
// we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
// event target node can't still be the shadow node.
- if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag))
- mev = prepareMouseEvent(HitTestRequest(true, true), mouseEvent);
+ if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNode()->hasTagName(inputTag)) {
+ HitTestRequest request(HitTestRequest::ReadOnly |
+ HitTestRequest::Active);
+ mev = prepareMouseEvent(request, mouseEvent);
+ }
Scrollbar* scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent);
if (!scrollbar)
@@ -1120,16 +1128,14 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
// This method only exists for platforms that don't know how to deliver
bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEvent)
{
- if (!m_frame->document())
- return false;
-
RefPtr<FrameView> protector(m_frame->view());
// We get this instead of a second mouse-up
m_mousePressed = false;
m_currentMousePosition = mouseEvent.pos();
- MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, true), mouseEvent);
+ HitTestRequest request(HitTestRequest::Active);
+ MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
Frame* subframe = subframeForHitTestResult(mev);
if (subframe && passMousePressEventToSubframe(mev, subframe)) {
m_capturingMouseEventsNode = 0;
@@ -1178,7 +1184,7 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi
// but also assert so that we can try to figure this out in debug
// builds, if it happens.
ASSERT(m_frame);
- if (!m_frame || !m_frame->document())
+ if (!m_frame)
return false;
RefPtr<FrameView> protector(m_frame->view());
@@ -1205,7 +1211,12 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi
// if we are allowed to select.
// This means that :hover and :active freeze in the state they were in when the mouse
// was pressed, rather than updating for nodes the mouse moves over as you hold the mouse down.
- HitTestRequest request(m_mousePressed && m_mouseDownMayStartSelect, m_mousePressed, true);
+ int hitType = HitTestRequest::MouseMove;
+ if (m_mousePressed && m_mouseDownMayStartSelect)
+ hitType |= HitTestRequest::ReadOnly;
+ if (m_mousePressed)
+ hitType |= HitTestRequest::Active;
+ HitTestRequest request(hitType);
MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
if (hoveredNode)
*hoveredNode = mev.hitTestResult();
@@ -1271,9 +1282,6 @@ void EventHandler::invalidateClick()
bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
{
- if (!m_frame->document())
- return false;
-
RefPtr<FrameView> protector(m_frame->view());
m_mousePressed = false;
@@ -1295,7 +1303,8 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
return m_lastScrollbarUnderMouse->mouseUp();
}
- MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, false, false, true), mouseEvent);
+ HitTestRequest request(HitTestRequest::MouseUp);
+ MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
Frame* subframe = m_capturingMouseEventsNode.get() ? subframeForTargetNode(m_capturingMouseEventsNode.get()) : subframeForHitTestResult(mev);
if (subframe && passMouseReleaseEventToSubframe(mev, subframe)) {
m_capturingMouseEventsNode = 0;
@@ -1325,6 +1334,8 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard)
{
+ m_frame->view()->resetDeferredRepaintDelay();
+
IntPoint contentsPos = m_frame->view()->windowToContents(event.pos());
RefPtr<MouseEvent> me = MouseEvent::create(eventType,
@@ -1334,7 +1345,7 @@ bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa
0, 0, clipboard);
ExceptionCode ec = 0;
- EventTargetNodeCast(dragTarget)->dispatchEvent(me.get(), ec);
+ dragTarget->dispatchEvent(me.get(), ec);
return me->defaultPrevented();
}
@@ -1342,13 +1353,11 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard*
{
bool accept = false;
- if (!m_frame->document())
- return false;
-
if (!m_frame->view())
return false;
-
- MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(true, false), event);
+
+ HitTestRequest request(HitTestRequest::ReadOnly);
+ MouseEventWithHitTestResults mev = prepareMouseEvent(request, event);
// Drag events should never go to text nodes (following IE, and proper mouseover/out dispatch)
Node* newTarget = mev.targetNode();
@@ -1361,12 +1370,13 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard*
// FIXME: this ordering was explicitly chosen to match WinIE. However,
// it is sometimes incorrect when dragging within subframes, as seen with
// LayoutTests/fast/events/drag-in-frames.html.
- if (newTarget)
+ if (newTarget) {
if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard);
else
accept = dispatchDragEvent(eventNames().dragenterEvent, newTarget, event, clipboard);
-
+ }
+
if (m_dragTarget) {
Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasTagName(iframeTag))
? static_cast<HTMLFrameElementBase*>(m_dragTarget.get())->contentFrame() : 0;
@@ -1376,11 +1386,12 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard*
dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard);
}
} else {
- if (newTarget)
+ if (newTarget) {
if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeTag))
accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentFrame()->eventHandler()->updateDragAndDrop(event, clipboard);
else
accept = dispatchDragEvent(eventNames().dragoverEvent, newTarget, event, clipboard);
+ }
}
m_dragTarget = newTarget;
@@ -1520,10 +1531,10 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
if (m_lastNodeUnderMouse != m_nodeUnderMouse) {
// send mouseout event to the old node
if (m_lastNodeUnderMouse)
- EventTargetNodeCast(m_lastNodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, eventNames().mouseoutEvent, 0, m_nodeUnderMouse.get());
+ m_lastNodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoutEvent, 0, m_nodeUnderMouse.get());
// send mouseover event to the new node
if (m_nodeUnderMouse)
- EventTargetNodeCast(m_nodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, eventNames().mouseoverEvent, 0, m_lastNodeUnderMouse.get());
+ m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventNames().mouseoverEvent, 0, m_lastNodeUnderMouse.get());
}
m_lastNodeUnderMouse = m_nodeUnderMouse;
#if ENABLE(SVG)
@@ -1534,12 +1545,14 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool /*cancelable*/, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder)
{
+ m_frame->view()->resetDeferredRepaintDelay();
+
updateMouseEventTargetNode(targetNode, mouseEvent, setUnder);
bool swallowEvent = false;
if (m_nodeUnderMouse)
- swallowEvent = EventTargetNodeCast(m_nodeUnderMouse.get())->dispatchMouseEvent(mouseEvent, eventType, clickCount);
+ swallowEvent = m_nodeUnderMouse->dispatchMouseEvent(mouseEvent, eventType, clickCount);
if (!swallowEvent && eventType == eventNames().mousedownEvent) {
// Blur current focus node when a link/button is clicked; this
@@ -1551,7 +1564,7 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe
// Walk up the render tree to search for a node to focus.
// Walking up the DOM tree wouldn't work for shadow trees, like those behind the engine-based text fields.
while (renderer) {
- node = renderer->element();
+ node = renderer->node();
if (node && node->isFocusable()) {
// To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus a
// node on mouse down if it's selected and inside a focused node. It will be
@@ -1560,7 +1573,7 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe
ExceptionCode ec = 0;
Node* n = node->isShadowNode() ? node->shadowParentNode() : node;
if (m_frame->selection()->isRange() &&
- m_frame->selection()->toRange()->compareNode(n, ec) == Range::NODE_INSIDE &&
+ m_frame->selection()->toNormalizedRange()->compareNode(n, ec) == Range::NODE_INSIDE &&
n->isDescendantOf(m_frame->document()->focusedNode()))
return false;
@@ -1586,8 +1599,6 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe
bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
{
Document* doc = m_frame->document();
- if (!doc)
- return false;
RenderObject* docRenderer = doc->renderer();
if (!docRenderer)
@@ -1597,7 +1608,7 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
IntPoint vPoint = m_frame->view()->windowToContents(e.pos());
- HitTestRequest request(true, false);
+ HitTestRequest request(HitTestRequest::ReadOnly);
HitTestResult result(vPoint);
doc->renderView()->layer()->hitTest(request, result);
Node* node = result.innerNode();
@@ -1616,11 +1627,16 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
}
node = node->shadowAncestorNode();
- EventTargetNodeCast(node)->dispatchWheelEvent(e);
+ node->dispatchWheelEvent(e);
if (e.isAccepted())
return true;
-
- if (node->renderer()) {
+
+ // If we don't have a renderer, send the wheel event to the first node we find with a renderer.
+ // This is needed for <option> and <optgroup> elements so that <select>s get a wheel scroll.
+ while (node && !node->renderer())
+ node = node->parent();
+
+ if (node && node->renderer()) {
// Just break up into two scrolls if we need to. Diagonal movement on
// a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
scrollAndAcceptEvent(e.deltaX(), ScrollLeft, ScrollRight, e, node);
@@ -1638,12 +1654,13 @@ bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
{
Document* doc = m_frame->document();
FrameView* v = m_frame->view();
- if (!doc || !v)
+ if (!v)
return false;
bool swallowEvent;
IntPoint viewportPos = v->windowToContents(event.pos());
- MouseEventWithHitTestResults mev = doc->prepareMouseEvent(HitTestRequest(false, true), viewportPos, event);
+ HitTestRequest request(HitTestRequest::Active);
+ MouseEventWithHitTestResults mev = doc->prepareMouseEvent(request, viewportPos, event);
// Context menu events shouldn't select text in GTK+ applications or in Chromium.
// FIXME: This should probably be configurable by embedders. Consider making it a WebPreferences setting.
@@ -1653,7 +1670,7 @@ bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
// FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
// If the selection is non-editable, we do word selection to make it easier to use the contextual menu items
// available for text selections. But only if we're above text.
- (m_frame->selection()->isContentEditable() || mev.targetNode() && mev.targetNode()->isTextNode())) {
+ (m_frame->selection()->isContentEditable() || (mev.targetNode() && mev.targetNode()->isTextNode()))) {
m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection
selectClosestWordOrLinkFromMouseEvent(mev);
}
@@ -1680,10 +1697,11 @@ bool EventHandler::canMouseDownStartSelect(Node* node)
if (!node->canStartSelection())
return false;
- for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())
- if (Node* node = curr->element())
- return EventTargetNodeCast(node)->dispatchEventForType(eventNames().selectstartEvent, true, true);
-
+ for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
+ if (Node* node = curr->node())
+ return node->dispatchEventForType(eventNames().selectstartEvent, true, true);
+ }
+
return true;
}
@@ -1692,10 +1710,11 @@ bool EventHandler::canMouseDragExtendSelect(Node* node)
if (!node || !node->renderer())
return true;
- for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())
- if (Node* node = curr->element())
- return EventTargetNodeCast(node)->dispatchEventForType(eventNames().selectstartEvent, true, true);
-
+ for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) {
+ if (Node* node = curr->node())
+ return node->dispatchEventForType(eventNames().selectstartEvent, true, true);
+ }
+
return true;
}
@@ -1718,26 +1737,23 @@ void EventHandler::hoverTimerFired(Timer<EventHandler>*)
ASSERT(m_frame->document());
if (RenderView* renderer = m_frame->contentRenderer()) {
+ HitTestRequest request(HitTestRequest::MouseMove);
HitTestResult result(m_frame->view()->windowToContents(m_currentMousePosition));
- renderer->layer()->hitTest(HitTestRequest(false, false, true), result);
+ renderer->layer()->hitTest(request, result);
m_frame->document()->updateRendering();
}
}
-static EventTargetNode* eventTargetNodeForDocument(Document* doc)
+static Node* eventTargetNodeForDocument(Document* doc)
{
if (!doc)
return 0;
Node* node = doc->focusedNode();
- if (!node) {
- if (doc->isHTMLDocument())
- node = doc->body();
- else
- node = doc->documentElement();
- if (!node)
- return 0;
- }
- return EventTargetNodeCast(node);
+ if (!node && doc->isHTMLDocument())
+ node = doc->body();
+ if (!node)
+ node = doc->documentElement();
+ return node;
}
bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt)
@@ -1780,9 +1796,11 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent)
// Check for cases where we are too early for events -- possible unmatched key up
// from pressing return in the location bar.
- RefPtr<EventTargetNode> node = eventTargetNodeForDocument(m_frame->document());
+ RefPtr<Node> node = eventTargetNodeForDocument(m_frame->document());
if (!node)
return false;
+
+ m_frame->view()->resetDeferredRepaintDelay();
// FIXME: what is this doing here, in keyboard event handler?
m_frame->loader()->resetMultipleFormSubmissionProtection();
@@ -1940,8 +1958,7 @@ void EventHandler::freeClipboard()
bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const
{
- ASSERT(node);
- if (node->hasChildNodes() || !m_frame->view())
+ if (!node || node->hasChildNodes() || !m_frame->view())
return false;
return m_frame->page() && m_frame->page()->dragController()->mayStartDragAtEventLocation(m_frame, point);
}
@@ -1994,7 +2011,7 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
// try to find an element that wants to be dragged
- HitTestRequest request(true, false);
+ HitTestRequest request(HitTestRequest::ReadOnly);
HitTestResult result(m_mouseDownPos);
m_frame->contentRenderer()->layer()->hitTest(request, result);
Node* node = result.innerNode();
@@ -2118,6 +2135,8 @@ bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEve
target = eventTargetNodeForDocument(m_frame->document());
if (!target)
return false;
+
+ m_frame->view()->resetDeferredRepaintDelay();
RefPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text);
event->setUnderlyingEvent(underlyingEvent);
@@ -2219,10 +2238,13 @@ void EventHandler::defaultTabEventHandler(KeyboardEvent* event)
void EventHandler::capsLockStateMayHaveChanged()
{
- if (Document* d = m_frame->document())
- if (Node* node = d->focusedNode())
- if (RenderObject* r = node->renderer())
- r->capsLockStateMayHaveChanged();
+ Document* d = m_frame->document();
+ if (Node* node = d->focusedNode()) {
+ if (RenderObject* r = node->renderer()) {
+ if (r->isTextField())
+ static_cast<RenderTextControlSingleLine*>(r)->capsLockStateMayHaveChanged();
+ }
+ }
}
unsigned EventHandler::pendingFrameUnloadEventCount()
@@ -2252,6 +2274,20 @@ void EventHandler::clearPendingFrameUnloadEventCount()
return;
}
+void EventHandler::sendResizeEvent()
+{
+ m_frame->document()->dispatchWindowEvent(eventNames().resizeEvent, false, false);
+}
+
+void EventHandler::sendScrollEvent()
+{
+ FrameView* v = m_frame->view();
+ if (!v)
+ return;
+ v->setWasScrolledByUser(true);
+ m_frame->document()->dispatchEventForType(eventNames().scrollEvent, true, false);
+}
+
unsigned EventHandler::pendingFrameBeforeUnloadEventCount()
{
return m_pendingFrameBeforeUnloadEventCount;
@@ -2308,7 +2344,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& e)
if (type == TouchEventStart) {
Frame* frame = m_frame;
IntPoint vPoint = frame->view()->windowToContents(e.pos());
- HitTestRequest request(true, false);
+ HitTestRequest request(HitTestRequest::ReadOnly);
HitTestResult result(vPoint);
frame->contentRenderer()->layer()->hitTest(request, result);
Node* node = result.innerNode();
@@ -2332,14 +2368,14 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& e)
}
}
- if (!node || !node->isEventTargetNode()) {
+ if (!node) {
// reset to the top document node
node = doc;
frame = m_frame;
vPoint = frame->view()->windowToContents(e.pos());
}
- m_touch = Touch::create(frame, EventTargetNodeCast(node), 0,
+ m_touch = Touch::create(frame, node, 0,
e.x(), e.y(), vPoint.x(), vPoint.y());
} else if (m_touch) {
if ((type == TouchEventMove) && (e.x() == m_touch->screenX()) &&
@@ -2386,7 +2422,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& e)
return false;
}
ExceptionCode ec = 0;
- static_cast<EventTargetNode*>(m_touch->target())->dispatchEvent(te.get(), ec);
+ m_touch->target()->dispatchEvent(te.get(), ec);
if (type == TouchEventEnd || type == TouchEventCancel) {
m_touch = 0;
}
diff --git a/WebCore/page/EventHandler.h b/WebCore/page/EventHandler.h
index 944bbd3..0a59eb3 100644
--- a/WebCore/page/EventHandler.h
+++ b/WebCore/page/EventHandler.h
@@ -49,11 +49,11 @@ namespace WebCore {
class AtomicString;
class Clipboard;
class Cursor;
-class EventTargetNode;
class Event;
class FloatPoint;
class FloatRect;
class Frame;
+class HitTestRequest;
class HitTestResult;
class HTMLFrameSetElement;
class KeyboardEvent;
@@ -75,8 +75,6 @@ class PlatformTouchEvent;
class Touch;
#endif
-struct HitTestRequest;
-
extern const int LinkDragHysteresis;
extern const int ImageDragHysteresis;
extern const int TextDragHysteresis;
@@ -101,7 +99,7 @@ public:
RenderObject* autoscrollRenderer() const;
void updateAutoscrollRenderer();
- HitTestResult hitTestResultAtPoint(const IntPoint&, bool allowShadowContent);
+ HitTestResult hitTestResultAtPoint(const IntPoint&, bool allowShadowContent, bool ignoreClipping = false);
bool mousePressed() const { return m_mousePressed; }
void setMousePressed(bool pressed) { m_mousePressed = pressed; }
@@ -174,6 +172,9 @@ public:
void addPendingFrameBeforeUnloadEventCount();
void removePendingFrameBeforeUnloadEventCount();
void clearPendingFrameBeforeUnloadEventCount();
+
+ void sendResizeEvent();
+ void sendScrollEvent();
#if PLATFORM(MAC)
PassRefPtr<KeyboardEvent> currentKeyboardEvent() const;
@@ -224,7 +225,9 @@ private:
void handleKeyboardSelectionMovement(KeyboardEvent*);
Cursor selectCursor(const MouseEventWithHitTestResults&, Scrollbar*);
+#if ENABLE(PAN_SCROLLING)
void setPanScrollCursor();
+#endif
void hoverTimerFired(Timer<EventHandler>*);
@@ -293,9 +296,12 @@ private:
void updateSelectionForMouseDrag(Node* targetNode, const IntPoint& localPoint);
+ bool capturesDragging() const { return m_capturesDragging; }
+
Frame* m_frame;
bool m_mousePressed;
+ bool m_capturesDragging;
RefPtr<Node> m_mousePressNode;
bool m_mouseDownMayStartSelect;
diff --git a/WebCore/page/FocusController.cpp b/WebCore/page/FocusController.cpp
index 9b30362..9760b3c 100644
--- a/WebCore/page/FocusController.cpp
+++ b/WebCore/page/FocusController.cpp
@@ -90,8 +90,6 @@ static Node* deepFocusableNode(FocusDirection direction, Node* node, KeyboardEve
break;
Document* document = owner->contentFrame()->document();
- if (!document)
- break;
node = (direction == FocusDirectionForward)
? document->nextFocusableNode(0, event)
@@ -115,8 +113,6 @@ bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* even
Frame* frame = focusedOrMainFrame();
ASSERT(frame);
Document* document = frame->document();
- if (!document)
- return false;
Node* node = (direction == FocusDirectionForward)
? document->nextFocusableNode(document->focusedNode(), event)
@@ -129,8 +125,6 @@ bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* even
break;
Document* parentDocument = parentFrame->document();
- if (!parentDocument)
- break;
HTMLFrameOwnerElement* owner = frame->ownerElement();
if (!owner)
@@ -155,10 +149,10 @@ bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* even
}
// Chrome doesn't want focus, so we should wrap focus.
- if (Document* d = m_page->mainFrame()->document())
- node = (direction == FocusDirectionForward)
- ? d->nextFocusableNode(0, event)
- : d->previousFocusableNode(0, event);
+ Document* d = m_page->mainFrame()->document();
+ node = (direction == FocusDirectionForward)
+ ? d->nextFocusableNode(0, event)
+ : d->previousFocusableNode(0, event);
node = deepFocusableNode(direction, node, event);
@@ -266,9 +260,9 @@ bool FocusController::setFocusedNode(Node* node, PassRefPtr<Frame> newFocusedFra
m_page->editorClient()->setInputMethodState(false);
return true;
}
-
- RefPtr<Document> newDocument = node ? node->document() : 0;
-
+
+ RefPtr<Document> newDocument = node->document();
+
if (newDocument && newDocument->focusedNode() == node) {
m_page->editorClient()->setInputMethodState(node->shouldUseInputMethod());
return true;
diff --git a/WebCore/page/Frame.cpp b/WebCore/page/Frame.cpp
index d4632e5..d379e13 100644
--- a/WebCore/page/Frame.cpp
+++ b/WebCore/page/Frame.cpp
@@ -5,7 +5,7 @@
* 2000 Simon Hausmann <hausmann@kde.org>
* 2000 Stefan Schimanski <1Stein@gmx.de>
* 2001 George Staikos <staikos@kde.org>
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2008 Eric Seidel <eric@webkit.org>
@@ -43,6 +43,7 @@
#include "FocusController.h"
#include "FloatQuad.h"
#include "FrameLoader.h"
+#include "FrameLoaderClient.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLDocument.h"
@@ -52,7 +53,6 @@
#include "HTMLNames.h"
#include "HTMLTableCellElement.h"
#include "HitTestResult.h"
-#include "JSDOMWindowShell.h"
#include "Logging.h"
#include "markup.h"
#include "MediaFeatureNames.h"
@@ -71,11 +71,15 @@
#include "XMLNames.h"
#include "ScriptController.h"
#include "npruntime_impl.h"
-#include "runtime_root.h"
#include "visible_units.h"
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/StdLibExtras.h>
+#if USE(JSC)
+#include "JSDOMWindowShell.h"
+#include "runtime_root.h"
+#endif
+
#if FRAME_LOADS_USER_STYLESHEET
#include "UserStyleSheetLoader.h"
#endif
@@ -286,7 +290,7 @@ Settings* Frame::settings() const
String Frame::selectedText() const
{
- return plainText(selection()->toRange().get());
+ return plainText(selection()->toNormalizedRange().get());
}
IntRect Frame::firstRectForRange(Range* range) const
@@ -405,7 +409,7 @@ String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellE
if (cellAboveRenderer) {
HTMLTableCellElement* aboveCell =
- static_cast<HTMLTableCellElement*>(cellAboveRenderer->element());
+ static_cast<HTMLTableCellElement*>(cellAboveRenderer->node());
if (aboveCell) {
// search within the above cell we found for a match
@@ -511,12 +515,12 @@ String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* e
return String();
}
-const Selection& Frame::mark() const
+const VisibleSelection& Frame::mark() const
{
return m_mark;
}
-void Frame::setMark(const Selection& s)
+void Frame::setMark(const VisibleSelection& s)
{
ASSERT(!s.base().node() || s.base().node()->document() == document());
ASSERT(!s.extent().node() || s.extent().node()->document() == document());
@@ -533,8 +537,8 @@ void Frame::notifyRendererOfSelectionChange(bool userTriggered)
renderer = selection()->rootEditableElement()->shadowAncestorNode()->renderer();
// If the current selection is in a textfield or textarea, notify the renderer that the selection has changed
- if (renderer && (renderer->isTextArea() || renderer->isTextField()))
- static_cast<RenderTextControl*>(renderer)->selectionChanged(userTriggered);
+ if (renderer && renderer->isTextControl())
+ toRenderTextControl(renderer)->selectionChanged(userTriggered);
}
void Frame::invalidateSelection()
@@ -577,7 +581,7 @@ static bool isFrameElement(const Node *n)
void Frame::setFocusedNodeIfNeeded()
{
- if (!document() || selection()->isNone() || !selection()->isFocusedAndActive())
+ if (selection()->isNone() || !selection()->isFocusedAndActive())
return;
Node* target = selection()->rootEditableElement();
@@ -596,7 +600,7 @@ void Frame::setFocusedNodeIfNeeded()
}
renderer = renderer->parent();
if (renderer)
- target = renderer->element();
+ target = renderer->node();
}
document()->setFocusedNode(0);
}
@@ -636,7 +640,7 @@ void Frame::selectionLayoutChanged()
if (!view)
return;
- Selection selection = this->selection()->selection();
+ VisibleSelection selection = this->selection()->selection();
if (!selection.isRange())
view->clearSelection();
@@ -657,7 +661,7 @@ void Frame::selectionLayoutChanged()
if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
RenderObject *startRenderer = startPos.node()->renderer();
RenderObject *endRenderer = endPos.node()->renderer();
- view->setSelection(startRenderer, startPos.offset(), endRenderer, endPos.offset());
+ view->setSelection(startRenderer, startPos.m_offset, endRenderer, endPos.m_offset);
}
}
}
@@ -708,7 +712,7 @@ bool Frame::shouldApplyTextZoom() const
if (m_zoomFactor == 1.0f || !isZoomFactorTextOnly())
return false;
#if ENABLE(SVG)
- if (m_doc && m_doc->isSVGDocument())
+ if (m_doc->isSVGDocument())
return false;
#endif
return true;
@@ -719,7 +723,7 @@ bool Frame::shouldApplyPageZoom() const
if (m_zoomFactor == 1.0f || isZoomFactorTextOnly())
return false;
#if ENABLE(SVG)
- if (m_doc && m_doc->isSVGDocument())
+ if (m_doc->isSVGDocument())
return false;
#endif
return true;
@@ -733,7 +737,7 @@ void Frame::setZoomFactor(float percent, bool isTextOnly)
#if ENABLE(SVG)
// SVG doesn't care if the zoom factor is text only. It will always apply a
// zoom to the whole SVG.
- if (m_doc && m_doc->isSVGDocument()) {
+ if (m_doc->isSVGDocument()) {
if (!static_cast<SVGDocument*>(m_doc.get())->zoomAndPanEnabled())
return;
m_zoomFactor = percent;
@@ -747,25 +751,21 @@ void Frame::setZoomFactor(float percent, bool isTextOnly)
m_zoomFactor = percent;
m_page->settings()->setZoomsTextOnly(isTextOnly);
- if (m_doc)
- m_doc->recalcStyle(Node::Force);
+ m_doc->recalcStyle(Node::Force);
for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
child->setZoomFactor(m_zoomFactor, isTextOnly);
- if (m_doc && m_doc->renderer() && m_doc->renderer()->needsLayout() && view()->didFirstLayout())
+ if (m_doc->renderer() && m_doc->renderer()->needsLayout() && view()->didFirstLayout())
view()->layout();
}
void Frame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize)
{
- if (!m_doc)
- return;
-
m_doc->setPrinting(printing);
view()->setMediaType(printing ? "print" : "screen");
m_doc->updateStyleSelector();
- forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize);
+ view()->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize);
for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
child->setPrinting(printing, minPageWidth, maxPageWidth, adjustViewSize);
@@ -797,6 +797,12 @@ String Frame::jsDefaultStatusBarText() const
void Frame::setNeedsReapplyStyles()
{
+ // When the frame is not showing web content, it doesn't make sense to apply styles.
+ // If we tried, we'd end up doing things with the document, but the document, if one
+ // exists, is not currently shown and should be in the page cache.
+ if (!m_loader.client()->hasHTMLView())
+ return;
+
if (m_needsReapplyStyles)
return;
@@ -817,11 +823,9 @@ void Frame::reapplyStyles()
{
m_needsReapplyStyles = false;
- // FIXME: This call doesn't really make sense in a method called
- // "reapplyStyles". We should probably eventually move it into its own
- // method.
- if (m_doc)
- m_doc->docLoader()->setAutoLoadImages(m_page && m_page->settings()->loadsImagesAutomatically());
+ // FIXME: This call doesn't really make sense in a function called reapplyStyles.
+ // We should probably eventually move it into its own function.
+ m_doc->docLoader()->setAutoLoadImages(m_page && m_page->settings()->loadsImagesAutomatically());
#if FRAME_LOADS_USER_STYLESHEET
const KURL userStyleSheetLocation = m_page ? m_page->settings()->userStyleSheetLocation() : KURL();
@@ -835,32 +839,29 @@ void Frame::reapplyStyles()
// The document automatically does this as required when you set the style sheet.
// But we had problems when this code was removed. Details are in
// <http://bugs.webkit.org/show_bug.cgi?id=8079>.
- if (m_doc)
- m_doc->updateStyleSelector();
+ m_doc->updateStyleSelector();
}
-bool Frame::shouldChangeSelection(const Selection& newSelection) const
+bool Frame::shouldChangeSelection(const VisibleSelection& newSelection) const
{
return shouldChangeSelection(selection()->selection(), newSelection, newSelection.affinity(), false);
}
-bool Frame::shouldChangeSelection(const Selection& oldSelection, const Selection& newSelection, EAffinity affinity, bool stillSelecting) const
+bool Frame::shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity affinity, bool stillSelecting) const
{
- return editor()->client()->shouldChangeSelectedRange(oldSelection.toRange().get(), newSelection.toRange().get(),
+ return editor()->client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange().get(), newSelection.toNormalizedRange().get(),
affinity, stillSelecting);
}
-bool Frame::shouldDeleteSelection(const Selection& selection) const
+bool Frame::shouldDeleteSelection(const VisibleSelection& selection) const
{
- return editor()->client()->shouldDeleteRange(selection.toRange().get());
+ return editor()->client()->shouldDeleteRange(selection.toNormalizedRange().get());
}
bool Frame::isContentEditable() const
{
if (m_editor.clientIsEditable())
return true;
- if (!m_doc)
- return false;
return m_doc->inDesignMode();
}
@@ -929,7 +930,7 @@ void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction edit
// Handle block styles, substracting these from the typing style.
RefPtr<CSSMutableStyleDeclaration> blockStyle = mutableStyle->copyBlockProperties();
blockStyle->diff(mutableStyle.get());
- if (document() && blockStyle->length() > 0)
+ if (blockStyle->length() > 0)
applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction));
// Set the remaining style as the typing style.
@@ -958,13 +959,10 @@ PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nod
{
nodeToRemove = 0;
- if (!document())
- return 0;
-
if (selection()->isNone())
return 0;
- RefPtr<Range> range(selection()->toRange());
+ RefPtr<Range> range(selection()->toNormalizedRange());
Position pos = range->editingStartPosition();
Element *elem = pos.element();
@@ -975,8 +973,7 @@ PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nod
ExceptionCode ec = 0;
if (m_typingStyle) {
- styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
- ASSERT(ec == 0);
+ styleElement = document()->createElement(spanTag, false);
styleElement->setAttribute(styleAttr, m_typingStyle->cssText().impl(), ec);
ASSERT(ec == 0);
@@ -1044,9 +1041,6 @@ void Frame::textDidChangeInTextArea(Element* e)
void Frame::applyEditingStyleToBodyElement() const
{
- if (!m_doc)
- return;
-
RefPtr<NodeList> list = m_doc->getElementsByTagName("body");
unsigned len = list->length();
for (unsigned i = 0; i < len; i++) {
@@ -1056,9 +1050,6 @@ void Frame::applyEditingStyleToBodyElement() const
void Frame::removeEditingStyleFromBodyElement() const
{
- if (!m_doc)
- return;
-
RefPtr<NodeList> list = m_doc->getElementsByTagName("body");
unsigned len = list->length();
for (unsigned i = 0; i < len; i++) {
@@ -1145,7 +1136,7 @@ RenderView* Frame::contentRenderer() const
if (!object)
return 0;
ASSERT(object->isRenderView());
- return static_cast<RenderView*>(object);
+ return toRenderView(object);
}
HTMLFrameOwnerElement* Frame::ownerElement() const
@@ -1208,7 +1199,7 @@ void Frame::selectionTextRects(Vector<FloatRect>& rects, bool clipToVisibleConte
if (!root)
return;
- RefPtr<Range> selectedRange = selection()->toRange();
+ RefPtr<Range> selectedRange = selection()->toNormalizedRange();
Vector<IntRect> intRects;
selectedRange->addLineBoxRects(intRects, true);
@@ -1223,15 +1214,6 @@ void Frame::selectionTextRects(Vector<FloatRect>& rects, bool clipToVisibleConte
}
-bool Frame::isFrameSet() const
-{
- Document* document = m_doc.get();
- if (!document || !document->isHTMLDocument())
- return false;
- Node *body = static_cast<HTMLDocument*>(document)->body();
- return body && body->renderer() && body->hasTagName(framesetTag);
-}
-
// Scans logically forward from "start", including any child frames
static HTMLFormElement *scanForForm(Node *start)
{
@@ -1271,66 +1253,32 @@ HTMLFormElement *Frame::currentForm() const
return start ? scanForForm(start) : 0;
}
-// FIXME: should this go in SelectionController?
-void Frame::revealSelection(const RenderLayer::ScrollAlignment& alignment) const
+void Frame::revealSelection(const ScrollAlignment& alignment, bool revealExtent)
{
IntRect rect;
-
- switch (selection()->state()) {
- case Selection::NONE:
+
+ switch (selection()->selectionType()) {
+ case VisibleSelection::NoSelection:
return;
-
- case Selection::CARET:
+ case VisibleSelection::CaretSelection:
rect = selection()->absoluteCaretBounds();
break;
-
- case Selection::RANGE:
- rect = enclosingIntRect(selectionBounds(false));
+ case VisibleSelection::RangeSelection:
+ rect = revealExtent ? VisiblePosition(selection()->extent()).absoluteCaretBounds() : enclosingIntRect(selectionBounds(false));
break;
}
Position start = selection()->start();
-
ASSERT(start.node());
if (start.node() && start.node()->renderer()) {
// FIXME: This code only handles scrolling the startContainer's layer, but
// the selection rect could intersect more than just that.
// See <rdar://problem/4799899>.
- if (RenderLayer *layer = start.node()->renderer()->enclosingLayer())
+ if (RenderLayer* layer = start.node()->renderer()->enclosingLayer())
layer->scrollRectToVisible(rect, false, alignment, alignment);
}
}
-void Frame::revealCaret(const RenderLayer::ScrollAlignment& alignment) const
-{
- if (selection()->isNone())
- return;
-
- Position extent = selection()->extent();
- if (extent.node() && extent.node()->renderer()) {
- IntRect extentRect = VisiblePosition(extent).absoluteCaretBounds();
- RenderLayer* layer = extent.node()->renderer()->enclosingLayer();
- if (layer)
- layer->scrollRectToVisible(extentRect, false, alignment, alignment);
- }
-}
-
-void Frame::adjustPageHeight(float* newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
-{
- RenderView* root = contentRenderer();
- if (root) {
- // Use a context with painting disabled.
- GraphicsContext context((PlatformGraphicsContext*)0);
- root->setTruncatedAt((int)floorf(oldBottom));
- IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
- root->layer()->paint(&context, dirtyRect);
- *newBottom = root->bestTruncatedAt();
- if (*newBottom == 0)
- *newBottom = oldBottom;
- } else
- *newBottom = oldBottom;
-}
-
Frame* Frame::frameForWidget(const Widget* widget)
{
ASSERT_ARG(widget, widget);
@@ -1345,67 +1293,6 @@ Frame* Frame::frameForWidget(const Widget* widget)
return static_cast<const FrameView*>(widget)->frame();
}
-void Frame::forceLayout(bool allowSubtree)
-{
- FrameView *v = m_view.get();
- if (v) {
- v->layout(allowSubtree);
- // We cannot unschedule a pending relayout, since the force can be called with
- // a tiny rectangle from a drawRect update. By unscheduling we in effect
- // "validate" and stop the necessary full repaint from occurring. Basically any basic
- // append/remove DHTML is broken by this call. For now, I have removed the optimization
- // until we have a better invalidation stategy. -dwh
- //v->unscheduleRelayout();
- }
-}
-
-void Frame::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth, bool adjustViewSize)
-{
- // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
- // the state of things before and after the layout
- RenderView *root = static_cast<RenderView*>(document()->renderer());
- if (root) {
- // This magic is basically copied from khtmlview::print
- int pageW = (int)ceilf(minPageWidth);
- root->setWidth(pageW);
- root->setNeedsLayoutAndPrefWidthsRecalc();
- forceLayout();
-
- // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
- // maximum page width, we will lay out to the maximum page width and clip extra content.
- // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
- // implementation should not do this!
- int rightmostPos = root->rightmostPosition();
- if (rightmostPos > minPageWidth) {
- pageW = min(rightmostPos, (int)ceilf(maxPageWidth));
- root->setWidth(pageW);
- root->setNeedsLayoutAndPrefWidthsRecalc();
- forceLayout();
- }
- }
-
- if (adjustViewSize && view())
- view()->adjustViewSize();
-}
-
-void Frame::sendResizeEvent()
-{
- if (Document* doc = document())
- doc->dispatchWindowEvent(eventNames().resizeEvent, false, false);
-}
-
-void Frame::sendScrollEvent()
-{
- FrameView* v = m_view.get();
- if (!v)
- return;
- v->setWasScrolledByUser(true);
- Document* doc = document();
- if (!doc)
- return;
- doc->dispatchEventForType(eventNames().scrollEvent, true, false);
-}
-
void Frame::clearTimers(FrameView *view, Document *document)
{
if (view) {
@@ -1428,8 +1315,6 @@ RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
{
nodeToRemove = 0;
- if (!document())
- return 0;
if (selection()->isNone())
return 0;
@@ -1443,10 +1328,9 @@ RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const
if (!m_typingStyle)
return node->renderer()->style();
- ExceptionCode ec = 0;
- RefPtr<Element> styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec);
- ASSERT(ec == 0);
+ RefPtr<Element> styleElement = document()->createElement(spanTag, false);
+ ExceptionCode ec = 0;
String styleText = m_typingStyle->cssText() + " display: inline";
styleElement->setAttribute(styleAttr, styleText.impl(), ec);
ASSERT(ec == 0);
@@ -1466,14 +1350,14 @@ void Frame::setSelectionFromNone()
// Put a caret inside the body if the entire frame is editable (either the
// entire WebView is editable or designMode is on for this document).
Document *doc = document();
- if (!doc || !selection()->isNone() || !isContentEditable())
+ if (!selection()->isNone() || !isContentEditable())
return;
Node* node = doc->documentElement();
while (node && !node->hasTagName(bodyTag))
node = node->traverseNextNode();
if (node)
- selection()->setSelection(Selection(Position(node, 0), DOWNSTREAM));
+ selection()->setSelection(VisibleSelection(Position(node, 0), DOWNSTREAM));
}
bool Frame::inViewSourceMode() const
@@ -1489,7 +1373,7 @@ void Frame::setInViewSourceMode(bool mode)
// Searches from the beginning of the document if nothing is selected.
bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection)
{
- if (target.isEmpty() || !document())
+ if (target.isEmpty())
return false;
if (excludeFromTextSearch())
@@ -1498,7 +1382,7 @@ bool Frame::findString(const String& target, bool forward, bool caseFlag, bool w
// Start from an edge of the selection, if there's a selection that's not in shadow content. Which edge
// is used depends on whether we're searching forward or backward, and whether startInSelection is set.
RefPtr<Range> searchRange(rangeOfContents(document()));
- Selection selection = this->selection()->selection();
+ VisibleSelection selection = this->selection()->selection();
if (forward)
setStart(searchRange.get(), startInSelection ? selection.visibleStart() : selection.visibleEnd());
@@ -1518,7 +1402,7 @@ bool Frame::findString(const String& target, bool forward, bool caseFlag, bool w
// If we started in the selection and the found range exactly matches the existing selection, find again.
// Build a selection with the found range to remove collapsed whitespace.
// Compare ranges instead of selection objects to ignore the way that the current selection was made.
- if (startInSelection && *Selection(resultRange.get()).toRange() == *selection.toRange()) {
+ if (startInSelection && *VisibleSelection(resultRange.get()).toNormalizedRange() == *selection.toNormalizedRange()) {
searchRange = rangeOfContents(document());
if (forward)
setStart(searchRange.get(), selection.visibleEnd());
@@ -1568,14 +1452,14 @@ bool Frame::findString(const String& target, bool forward, bool caseFlag, bool w
if (resultRange->collapsed(exception))
return false;
- this->selection()->setSelection(Selection(resultRange.get(), DOWNSTREAM));
+ this->selection()->setSelection(VisibleSelection(resultRange.get(), DOWNSTREAM));
revealSelection();
return true;
}
unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit)
{
- if (target.isEmpty() || !document())
+ if (target.isEmpty())
return 0;
RefPtr<Range> searchRange(rangeOfContents(document()));
@@ -1618,7 +1502,7 @@ unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsig
// Do a "fake" paint in order to execute the code that computes the rendered rect for
// each text match.
Document* doc = document();
- if (doc && m_view && contentRenderer()) {
+ if (m_view && contentRenderer()) {
doc->updateLayout(); // Ensure layout is up to date.
IntRect visibleRect = m_view->visibleContentRect();
if (!visibleRect.isEmpty()) {
@@ -1638,7 +1522,7 @@ bool Frame::markedTextMatchesAreHighlighted() const
void Frame::setMarkedTextMatchesAreHighlighted(bool flag)
{
- if (flag == m_highlightTextMatches || !document())
+ if (flag == m_highlightTextMatches)
return;
m_highlightTextMatches = flag;
@@ -1718,10 +1602,8 @@ void Frame::disconnectOwnerElement()
String Frame::documentTypeString() const
{
- if (Document* doc = document()) {
- if (DocumentType* doctype = doc->doctype())
- return createMarkup(doctype);
- }
+ if (DocumentType* doctype = document()->doctype())
+ return createMarkup(doctype);
return String();
}
@@ -1755,8 +1637,6 @@ bool Frame::shouldClose()
return true;
RefPtr<Document> doc = document();
- if (!doc)
- return true;
HTMLElement* body = doc->body();
if (!body)
return true;
@@ -1765,7 +1645,7 @@ bool Frame::shouldClose()
beforeUnloadEvent->setTarget(doc);
doc->handleWindowEvent(beforeUnloadEvent.get(), false);
- if (!beforeUnloadEvent->defaultPrevented() && doc)
+ if (!beforeUnloadEvent->defaultPrevented())
doc->defaultEventHandler(beforeUnloadEvent.get());
if (beforeUnloadEvent->result().isNull())
return true;
@@ -1785,52 +1665,50 @@ void Frame::scheduleClose()
chrome->closeWindowSoon();
}
-void Frame::respondToChangedSelection(const Selection& oldSelection, bool closeTyping)
+void Frame::respondToChangedSelection(const VisibleSelection& oldSelection, bool closeTyping)
{
- if (document()) {
- bool isContinuousSpellCheckingEnabled = editor()->isContinuousSpellCheckingEnabled();
- bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && editor()->isGrammarCheckingEnabled();
- if (isContinuousSpellCheckingEnabled) {
- Selection newAdjacentWords;
- Selection newSelectedSentence;
- if (selection()->selection().isContentEditable()) {
- VisiblePosition newStart(selection()->selection().visibleStart());
- newAdjacentWords = Selection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
- if (isContinuousGrammarCheckingEnabled)
- newSelectedSentence = Selection(startOfSentence(newStart), endOfSentence(newStart));
- }
+ bool isContinuousSpellCheckingEnabled = editor()->isContinuousSpellCheckingEnabled();
+ bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && editor()->isGrammarCheckingEnabled();
+ if (isContinuousSpellCheckingEnabled) {
+ VisibleSelection newAdjacentWords;
+ VisibleSelection newSelectedSentence;
+ if (selection()->selection().isContentEditable()) {
+ VisiblePosition newStart(selection()->selection().visibleStart());
+ newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
+ if (isContinuousGrammarCheckingEnabled)
+ newSelectedSentence = VisibleSelection(startOfSentence(newStart), endOfSentence(newStart));
+ }
- // When typing we check spelling elsewhere, so don't redo it here.
- // If this is a change in selection resulting from a delete operation,
- // oldSelection may no longer be in the document.
- if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) {
- VisiblePosition oldStart(oldSelection.visibleStart());
- Selection oldAdjacentWords = Selection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));
- if (oldAdjacentWords != newAdjacentWords) {
- editor()->markMisspellings(oldAdjacentWords);
- if (isContinuousGrammarCheckingEnabled) {
- Selection oldSelectedSentence = Selection(startOfSentence(oldStart), endOfSentence(oldStart));
- if (oldSelectedSentence != newSelectedSentence)
- editor()->markBadGrammar(oldSelectedSentence);
- }
+ // When typing we check spelling elsewhere, so don't redo it here.
+ // If this is a change in selection resulting from a delete operation,
+ // oldSelection may no longer be in the document.
+ if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) {
+ VisiblePosition oldStart(oldSelection.visibleStart());
+ VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));
+ if (oldAdjacentWords != newAdjacentWords) {
+ if (isContinuousGrammarCheckingEnabled) {
+ VisibleSelection oldSelectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart));
+ editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, oldSelectedSentence != newSelectedSentence, oldSelectedSentence);
+ } else {
+ editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords);
}
}
-
- // This only erases markers that are in the first unit (word or sentence) of the selection.
- // Perhaps peculiar, but it matches AppKit.
- if (RefPtr<Range> wordRange = newAdjacentWords.toRange())
- document()->removeMarkers(wordRange.get(), DocumentMarker::Spelling);
- if (RefPtr<Range> sentenceRange = newSelectedSentence.toRange())
- document()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
}
- // When continuous spell checking is off, existing markers disappear after the selection changes.
- if (!isContinuousSpellCheckingEnabled)
- document()->removeMarkers(DocumentMarker::Spelling);
- if (!isContinuousGrammarCheckingEnabled)
- document()->removeMarkers(DocumentMarker::Grammar);
+ // This only erases markers that are in the first unit (word or sentence) of the selection.
+ // Perhaps peculiar, but it matches AppKit.
+ if (RefPtr<Range> wordRange = newAdjacentWords.toNormalizedRange())
+ document()->removeMarkers(wordRange.get(), DocumentMarker::Spelling);
+ if (RefPtr<Range> sentenceRange = newSelectedSentence.toNormalizedRange())
+ document()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
}
+ // When continuous spell checking is off, existing markers disappear after the selection changes.
+ if (!isContinuousSpellCheckingEnabled)
+ document()->removeMarkers(DocumentMarker::Spelling);
+ if (!isContinuousGrammarCheckingEnabled)
+ document()->removeMarkers(DocumentMarker::Grammar);
+
editor()->respondToChangedSelection(oldSelection);
}
@@ -1843,7 +1721,7 @@ VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
RenderObject* renderer = node->renderer();
if (!renderer)
return VisiblePosition();
- VisiblePosition visiblePos = renderer->positionForCoordinates(result.localPoint().x(), result.localPoint().y());
+ VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint());
if (visiblePos.isNull())
visiblePos = VisiblePosition(Position(node, 0));
return visiblePos;
@@ -1862,4 +1740,47 @@ Document* Frame::documentAtPoint(const IntPoint& point)
return result.innerNode() ? result.innerNode()->document() : 0;
}
+void Frame::createView(const IntSize& viewportSize,
+ const Color& backgroundColor, bool transparent,
+ const IntSize& fixedLayoutSize, bool useFixedLayout,
+ ScrollbarMode horizontalScrollbarMode, ScrollbarMode verticalScrollbarMode)
+{
+ ASSERT(this);
+ ASSERT(m_page);
+
+ bool isMainFrame = this == m_page->mainFrame();
+
+ if (isMainFrame && view())
+ view()->setParentVisible(false);
+
+ setView(0);
+
+ FrameView* frameView;
+ if (isMainFrame) {
+ frameView = new FrameView(this, viewportSize);
+ frameView->setFixedLayoutSize(fixedLayoutSize);
+ frameView->setUseFixedLayout(useFixedLayout);
+ } else
+ frameView = new FrameView(this);
+
+ frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode);
+ frameView->updateDefaultScrollbarState();
+
+ setView(frameView);
+ // FrameViews are created with a ref count of 1. Release this ref since we've assigned it to frame.
+ frameView->deref();
+
+ if (backgroundColor.isValid())
+ frameView->updateBackgroundRecursively(backgroundColor, transparent);
+
+ if (isMainFrame)
+ frameView->setParentVisible(true);
+
+ if (ownerRenderer())
+ ownerRenderer()->setWidget(frameView);
+
+ if (HTMLFrameOwnerElement* owner = ownerElement())
+ view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
+}
+
} // namespace WebCore
diff --git a/WebCore/page/Frame.h b/WebCore/page/Frame.h
index bebdc63..5d46acd 100644
--- a/WebCore/page/Frame.h
+++ b/WebCore/page/Frame.h
@@ -29,6 +29,7 @@
#define Frame_h
#include "AnimationController.h"
+#include "Document.h"
#include "DragImage.h"
#include "EditAction.h"
#include "Editor.h"
@@ -36,7 +37,7 @@
#include "FrameLoader.h"
#include "FrameTree.h"
#include "Range.h"
-#include "RenderLayer.h"
+#include "ScrollBehavior.h"
#include "ScriptController.h"
#include "SelectionController.h"
#include "TextGranularity.h"
@@ -61,19 +62,21 @@ typedef struct HBITMAP__* HBITMAP;
namespace WebCore {
+class CSSMutableStyleDeclaration;
class Editor;
class EventHandler;
class FrameLoader;
class FrameLoaderClient;
-class FramePrivate;
class FrameTree;
+class FrameView;
class HTMLFrameOwnerElement;
class HTMLTableCellElement;
-class ScriptController;
class RegularExpression;
class RenderPart;
-class Selection;
+class ScriptController;
class SelectionController;
+class Settings;
+class VisibleSelection;
class Widget;
#if FRAME_LOADS_USER_STYLESHEET
@@ -122,7 +125,9 @@ public:
bool excludeFromTextSearch() const;
void setExcludeFromTextSearch(bool);
- friend class FramePrivate;
+ void createView(const IntSize&, const Color&, bool, const IntSize &, bool,
+ ScrollbarMode = ScrollbarAuto, ScrollbarMode = ScrollbarAuto);
+
private:
Frame(Page*, HTMLFrameOwnerElement*, FrameLoaderClient*);
@@ -172,25 +177,9 @@ public:
private:
void lifeSupportTimerFired(Timer<Frame>*);
-// === to be moved into Document
-
-public:
- bool isFrameSet() const;
-
-// === to be moved into EventHandler
-
-public:
- void sendResizeEvent();
- void sendScrollEvent();
-
// === to be moved into FrameView
public:
- void forceLayout(bool allowSubtree = false);
- void forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth, bool adjustViewSize);
-
- void adjustPageHeight(float* newBottom, float oldTop, float oldBottom, float bottomLimit);
-
void setZoomFactor(float scale, bool isTextOnly);
float zoomFactor() const;
bool isZoomFactorTextOnly() const;
@@ -218,8 +207,8 @@ public:
String selectedText() const;
bool findString(const String&, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection);
- const Selection& mark() const; // Mark, to be used as emacs uses it.
- void setMark(const Selection&);
+ const VisibleSelection& mark() const; // Mark, to be used as emacs uses it.
+ void setMark(const VisibleSelection&);
void computeAndSetTypingStyle(CSSStyleDeclaration* , EditAction = EditActionUnspecified);
String selectionStartStylePropertyValue(int stylePropertyID) const;
@@ -230,8 +219,8 @@ public:
IntRect firstRectForRange(Range*) const;
- void respondToChangedSelection(const Selection& oldSelection, bool closeTyping);
- bool shouldChangeSelection(const Selection& oldSelection, const Selection& newSelection, EAffinity, bool stillSelecting) const;
+ void respondToChangedSelection(const VisibleSelection& oldSelection, bool closeTyping);
+ bool shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity, bool stillSelecting) const;
RenderStyle* styleForSelectionStart(Node*& nodeToRemove) const;
@@ -256,8 +245,8 @@ public:
TextGranularity selectionGranularity() const;
void setSelectionGranularity(TextGranularity);
- bool shouldChangeSelection(const Selection&) const;
- bool shouldDeleteSelection(const Selection&) const;
+ bool shouldChangeSelection(const VisibleSelection&) const;
+ bool shouldDeleteSelection(const VisibleSelection&) const;
void clearCaretRectIfNeeded();
void setFocusedNodeIfNeeded();
void selectionLayoutChanged();
@@ -281,9 +270,8 @@ public:
void selectionTextRects(Vector<FloatRect>&, bool clipToVisibleContent = true) const;
HTMLFormElement* currentForm() const;
-
- void revealSelection(const RenderLayer::ScrollAlignment& = RenderLayer::gAlignCenterIfNeeded) const;
- void revealCaret(const RenderLayer::ScrollAlignment& = RenderLayer::gAlignCenterIfNeeded) const;
+
+ void revealSelection(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, bool revealExtent = false);
void setSelectionFromNone();
void setUseSecureKeyboardEntry(bool);
@@ -359,7 +347,7 @@ private:
TextGranularity m_selectionGranularity;
mutable SelectionController m_selectionController;
- mutable Selection m_mark;
+ mutable VisibleSelection m_mark;
Timer<Frame> m_caretBlinkTimer;
mutable Editor m_editor;
mutable EventHandler m_eventHandler;
diff --git a/WebCore/page/FrameTree.cpp b/WebCore/page/FrameTree.cpp
index c9b4172..adb5c90 100644
--- a/WebCore/page/FrameTree.cpp
+++ b/WebCore/page/FrameTree.cpp
@@ -82,10 +82,6 @@ void FrameTree::appendChild(PassRefPtr<Frame> child)
void FrameTree::removeChild(Frame* child)
{
child->tree()->m_parent = 0;
- child->setView(0);
- if (child->ownerElement())
- child->page()->decrementFrameCount();
- child->pageDestroyed();
// Slightly tricky way to prevent deleting the child until we are done with it, w/o
// extra refs. These swaps leave the child in a circular list by itself. Clearing its
diff --git a/WebCore/page/FrameTree.h b/WebCore/page/FrameTree.h
index 3b74d5d..d4c8c43 100644
--- a/WebCore/page/FrameTree.h
+++ b/WebCore/page/FrameTree.h
@@ -56,6 +56,7 @@ namespace WebCore {
Frame* traversePreviousWithWrap(bool) const;
void appendChild(PassRefPtr<Frame>);
+ void detachFromParent() { m_parent = 0; }
void removeChild(Frame*);
Frame* child(unsigned index) const;
diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp
index 2eefd6c..5f1ee65 100644
--- a/WebCore/page/FrameView.cpp
+++ b/WebCore/page/FrameView.cpp
@@ -28,6 +28,7 @@
#include "AXObjectCache.h"
#include "CSSStyleSelector.h"
#include "ChromeClient.h"
+#include "DocLoader.h"
#include "EventHandler.h"
#include "FloatRect.h"
#include "FocusController.h"
@@ -55,15 +56,41 @@
#include "TimeCounter.h"
#endif
+#if USE(ACCELERATED_COMPOSITING)
+#include "RenderLayerCompositor.h"
+#endif
+
namespace WebCore {
using namespace HTMLNames;
double FrameView::sCurrentPaintTimeStamp = 0.0;
+#if ENABLE(REPAINT_THROTTLING)
+// Normal delay
+static const double deferredRepaintDelay = 0.025;
+// Negative value would mean that first few repaints happen without a delay
+static const double initialDeferredRepaintDelayDuringLoading = 0;
+// The delay grows on each repaint to this maximum value
+static const double maxDeferredRepaintDelayDuringLoading = 2.5;
+// On each repaint the delay increses by this amount
+static const double deferredRepaintDelayIncrementDuringLoading = 0.5;
+#else
+// FIXME: Repaint throttling could be good to have on all platform.
+// The balance between CPU use and repaint frequency will need some tuning for desktop.
+// More hooks may be needed to reset the delay on things like GIF and CSS animations.
+static const double deferredRepaintDelay = 0;
+static const double initialDeferredRepaintDelayDuringLoading = 0;
+static const double maxDeferredRepaintDelayDuringLoading = 0;
+static const double deferredRepaintDelayIncrementDuringLoading = 0;
+#endif
+
+// The maximum number of updateWidgets iterations that should be done before returning.
+static const unsigned maxUpdateWidgetsIterations = 2;
+
struct ScheduledEvent {
RefPtr<Event> m_event;
- RefPtr<EventTargetNode> m_eventTarget;
+ RefPtr<Node> m_eventTarget;
};
FrameView::FrameView(Frame* frame)
@@ -84,6 +111,7 @@ FrameView::FrameView(Frame* frame)
, m_viewportRenderer(0)
, m_wasScrolledByUser(false)
, m_inProgrammaticScroll(false)
+ , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
, m_shouldUpdateWhileOffscreen(true)
{
init();
@@ -108,6 +136,7 @@ FrameView::FrameView(Frame* frame, const IntSize& initialSize)
, m_viewportRenderer(0)
, m_wasScrolledByUser(false)
, m_inProgrammaticScroll(false)
+ , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired)
, m_shouldUpdateWhileOffscreen(true)
{
init();
@@ -132,7 +161,7 @@ FrameView::~FrameView()
ASSERT(!m_enqueueEvents);
if (m_frame) {
- ASSERT(m_frame->view() != this || !m_frame->document() || !m_frame->contentRenderer());
+ ASSERT(m_frame->view() != this || !m_frame->contentRenderer());
RenderPart* renderer = m_frame->ownerRenderer();
if (renderer && renderer->widget() == this)
renderer->setWidget(0);
@@ -160,8 +189,10 @@ void FrameView::reset()
m_lastZoomFactor = 1.0f;
m_deferringRepaints = 0;
m_repaintCount = 0;
- m_repaintRect = IntRect();
m_repaintRects.clear();
+ m_deferredRepaintDelay = initialDeferredRepaintDelayDuringLoading;
+ m_deferredRepaintTimer.stop();
+ m_lastPaintTime = 0;
m_paintRestriction = PaintRestrictionNone;
m_isPainting = false;
m_isVisuallyNonEmpty = false;
@@ -286,22 +317,20 @@ PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientatio
{
// FIXME: We need to update the scrollbar dynamically as documents change (or as doc elements and bodies get discovered that have custom styles).
Document* doc = m_frame->document();
- if (!doc)
- return ScrollView::createScrollbar(orientation);
// Try the <body> element first as a scrollbar source.
Element* body = doc->body();
- if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(RenderStyle::SCROLLBAR))
+ if (body && body->renderer() && body->renderer()->style()->hasPseudoStyle(SCROLLBAR))
return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderBox());
// If the <body> didn't have a custom style, then the root element might.
Element* docElement = doc->documentElement();
- if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(RenderStyle::SCROLLBAR))
+ if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR))
return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox());
// If we have an owning iframe/frame element, then it can set the custom scrollbar also.
RenderPart* frameRenderer = m_frame->ownerRenderer();
- if (frameRenderer && frameRenderer->style()->hasPseudoStyle(RenderStyle::SCROLLBAR))
+ if (frameRenderer && frameRenderer->style()->hasPseudoStyle(SCROLLBAR))
return RenderScrollbar::createCustomScrollbar(this, orientation, frameRenderer);
// Nobody set a custom style, so we just use a native scrollbar.
@@ -367,6 +396,41 @@ void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, S
m_viewportRenderer = o;
}
+#if USE(ACCELERATED_COMPOSITING)
+void FrameView::updateCompositingLayers(CompositingUpdate updateType)
+{
+ RenderView* view = m_frame->contentRenderer();
+ if (!view || !view->usesCompositing())
+ return;
+
+ if (updateType == ForcedCompositingUpdate)
+ view->compositor()->setCompositingLayersNeedUpdate();
+
+ view->compositor()->updateCompositingLayers();
+}
+
+void FrameView::setNeedsOneShotDrawingSynchronization()
+{
+ Page* page = frame() ? frame()->page() : 0;
+ if (page)
+ page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+void FrameView::didMoveOnscreen()
+{
+ RenderView* view = m_frame->contentRenderer();
+ if (view)
+ view->didMoveOnscreen();
+}
+
+void FrameView::willMoveOffscreen()
+{
+ RenderView* view = m_frame->contentRenderer();
+ if (view)
+ view->willMoveOffscreen();
+}
+
RenderObject* FrameView::layoutRoot(bool onlyDuringLayout) const
{
return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
@@ -408,11 +472,6 @@ void FrameView::layout(bool allowSubtree)
return;
Document* document = m_frame->document();
- if (!document) {
- // FIXME: Should we set m_size.height here too?
- m_size.setWidth(layoutWidth());
- return;
- }
m_layoutSchedulingEnabled = false;
@@ -484,7 +543,7 @@ void FrameView::layout(bool allowSubtree)
#endif
}
- m_doFullRepaint = !subtree && (m_firstLayout || static_cast<RenderView*>(root)->printing());
+ m_doFullRepaint = !subtree && (m_firstLayout || toRenderView(root)->printing());
if (!subtree) {
// Now set our scrollbar state for the layout.
@@ -539,13 +598,17 @@ void FrameView::layout(bool allowSubtree)
m_layoutSchedulingEnabled = true;
- if (!subtree && !static_cast<RenderView*>(root)->printing())
+ if (!subtree && !toRenderView(root)->printing())
adjustViewSize();
// Now update the positions of all layers.
beginDeferredRepaints();
layer->updateLayerPositions(m_doFullRepaint);
endDeferredRepaints();
+
+#if USE(ACCELERATED_COMPOSITING)
+ updateCompositingLayers();
+#endif
m_layoutCount++;
@@ -573,7 +636,7 @@ void FrameView::layout(bool allowSubtree)
// Calls resumeScheduledEvents()
performPostLayoutTasks();
- if (needsLayout()) {
+ if (!m_postLayoutTasksTimer.isActive() && needsLayout()) {
// Post-layout widget updates or an event handler made us need layout again.
// Lay out again, but this time defer widget updates and event dispatch until after
// we return.
@@ -680,21 +743,31 @@ void FrameView::repaintContentRectangle(const IntRect& r, bool immediate)
{
ASSERT(!m_frame->document()->ownerElement());
- if (m_deferringRepaints && !immediate) {
+ double delay = adjustedDeferredRepaintDelay();
+ if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) {
IntRect visibleContent = visibleContentRect();
visibleContent.intersect(r);
- if (!visibleContent.isEmpty()) {
- m_repaintCount++;
- m_repaintRect.unite(r);
- if (m_repaintCount == cRepaintRectUnionThreshold)
- m_repaintRects.clear();
- else if (m_repaintCount < cRepaintRectUnionThreshold)
- m_repaintRects.append(r);
- }
#ifdef ANDROID_CAPTURE_OFFSCREEN_PAINTS
- else
+ if (visibleContent.isEmpty())
ScrollView::platformOffscreenContentRectangle(r);
#endif
+ if (visibleContent.isEmpty())
+ return;
+ if (m_repaintCount == cRepaintRectUnionThreshold) {
+ IntRect unionedRect;
+ for (unsigned i = 0; i < cRepaintRectUnionThreshold; ++i)
+ unionedRect.unite(m_repaintRects[i]);
+ m_repaintRects.clear();
+ m_repaintRects.append(unionedRect);
+ }
+ if (m_repaintCount < cRepaintRectUnionThreshold)
+ m_repaintRects.append(r);
+ else
+ m_repaintRects[0].unite(r);
+ m_repaintCount++;
+
+ if (!m_deferringRepaints && !m_deferredRepaintTimer.isActive())
+ m_deferredRepaintTimer.startOneShot(delay);
return;
}
@@ -711,15 +784,6 @@ void FrameView::beginDeferredRepaints()
return page->mainFrame()->view()->beginDeferredRepaints();
m_deferringRepaints++;
-#ifdef ANDROID_FIX // This allows sub frames to accumulate deferred repaints
- if (m_deferringRepaints == 1) {
-#endif
- m_repaintCount = 0;
- m_repaintRect = IntRect();
- m_repaintRects.clear();
-#ifdef ANDROID_FIX
- }
-#endif
}
@@ -730,22 +794,90 @@ void FrameView::endDeferredRepaints()
return page->mainFrame()->view()->endDeferredRepaints();
ASSERT(m_deferringRepaints > 0);
- if (--m_deferringRepaints == 0) {
- if (m_repaintCount >= cRepaintRectUnionThreshold)
- repaintContentRectangle(m_repaintRect, false);
- else {
- unsigned size = m_repaintRects.size();
- for (unsigned i = 0; i < size; i++)
- repaintContentRectangle(m_repaintRects[i], false);
- m_repaintRects.clear();
- }
+
+ if (--m_deferringRepaints)
+ return;
+
+ if (m_deferredRepaintTimer.isActive())
+ return;
+
+ if (double delay = adjustedDeferredRepaintDelay()) {
+ m_deferredRepaintTimer.startOneShot(delay);
+ return;
}
+
+ doDeferredRepaints();
}
+void FrameView::checkStopDelayingDeferredRepaints()
+{
+ if (!m_deferredRepaintTimer.isActive())
+ return;
+
+ Document* document = m_frame->document();
+ if (document && (document->parsing() || document->docLoader()->requestCount()))
+ return;
+
+ m_deferredRepaintTimer.stop();
+
+ doDeferredRepaints();
+}
+
+void FrameView::doDeferredRepaints()
+{
+ ASSERT(!m_deferringRepaints);
+ if (isOffscreen() && !shouldUpdateWhileOffscreen()) {
+ m_repaintRects.clear();
+ m_repaintCount = 0;
+ return;
+ }
+ unsigned size = m_repaintRects.size();
+ for (unsigned i = 0; i < size; i++)
+ ScrollView::repaintContentRectangle(m_repaintRects[i], false);
+ m_repaintRects.clear();
+ m_repaintCount = 0;
+
+ updateDeferredRepaintDelay();
+}
+
+void FrameView::updateDeferredRepaintDelay()
+{
+ Document* document = m_frame->document();
+ if (!document || (!document->parsing() && !document->docLoader()->requestCount())) {
+ m_deferredRepaintDelay = deferredRepaintDelay;
+ return;
+ }
+ if (m_deferredRepaintDelay < maxDeferredRepaintDelayDuringLoading) {
+ m_deferredRepaintDelay += deferredRepaintDelayIncrementDuringLoading;
+ if (m_deferredRepaintDelay > maxDeferredRepaintDelayDuringLoading)
+ m_deferredRepaintDelay = maxDeferredRepaintDelayDuringLoading;
+ }
+}
+
+void FrameView::resetDeferredRepaintDelay()
+{
+ m_deferredRepaintDelay = 0;
+ if (m_deferredRepaintTimer.isActive())
+ m_deferredRepaintTimer.startOneShot(0);
+}
+
+double FrameView::adjustedDeferredRepaintDelay() const
+{
+ if (!m_deferredRepaintDelay)
+ return 0;
+ double timeSinceLastPaint = currentTime() - m_lastPaintTime;
+ return max(0., m_deferredRepaintDelay - timeSinceLastPaint);
+}
+
+void FrameView::deferredRepaintTimerFired(Timer<FrameView>*)
+{
+ doDeferredRepaints();
+}
+
void FrameView::layoutTimerFired(Timer<FrameView>*)
{
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (m_frame->document() && !m_frame->document()->ownerElement())
+ if (!m_frame->document()->ownerElement())
printf("Layout timer fired at %d\n", m_frame->document()->elapsedTime());
#endif
layout();
@@ -753,7 +885,7 @@ void FrameView::layoutTimerFired(Timer<FrameView>*)
void FrameView::scheduleRelayout()
{
- ASSERT(!m_frame->document() || !m_frame->document()->inPageCache());
+ ASSERT(!m_frame->document()->inPageCache());
ASSERT(m_frame->view() == this);
if (m_layoutRoot) {
@@ -764,7 +896,7 @@ void FrameView::scheduleRelayout()
return;
if (!needsLayout())
return;
- if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout())
+ if (!m_frame->document()->shouldScheduleLayout())
return;
#if defined(FLATTEN_IFRAME) || defined(FLATTEN_FRAMESET)
@@ -858,7 +990,7 @@ bool FrameView::needsLayout() const
return layoutPending()
|| (root && root->needsLayout())
|| m_layoutRoot
- || (document && document->hasChangedChild()) // can occur when using WebKit ObjC interface
+ || document->hasChangedChild() // can occur when using WebKit ObjC interface
|| m_frame->needsReapplyStyles();
}
@@ -875,7 +1007,7 @@ void FrameView::unscheduleRelayout()
return;
#ifdef INSTRUMENT_LAYOUT_SCHEDULING
- if (m_frame->document() && !m_frame->document()->ownerElement())
+ if (!m_frame->document()->ownerElement())
printf("Layout timer unscheduled at %d\n", m_frame->document()->elapsedTime());
#endif
@@ -927,7 +1059,7 @@ void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen)
m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen;
}
-void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<EventTargetNode> eventTarget)
+void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget)
{
if (!m_enqueueEvents) {
ExceptionCode ec = 0;
@@ -955,6 +1087,29 @@ void FrameView::resumeScheduledEvents()
ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents);
}
+bool FrameView::updateWidgets()
+{
+ if (m_nestedLayoutCount > 1 || !m_widgetUpdateSet || m_widgetUpdateSet->isEmpty())
+ return true;
+
+ Vector<RenderPartObject*> objectVector;
+ copyToVector(*m_widgetUpdateSet, objectVector);
+ size_t size = objectVector.size();
+ for (size_t i = 0; i < size; ++i) {
+ RenderPartObject* object = objectVector[i];
+ object->updateWidget(false);
+
+ // updateWidget() can destroy the RenderPartObject, so we need to make sure it's
+ // alive by checking if it's still in m_widgetUpdateSet.
+ if (m_widgetUpdateSet->contains(object)) {
+ object->updateWidgetPosition();
+ m_widgetUpdateSet->remove(object);
+ }
+ }
+
+ return m_widgetUpdateSet->isEmpty();
+}
+
void FrameView::performPostLayoutTasks()
{
if (m_firstLayoutCallbackPending) {
@@ -970,22 +1125,12 @@ void FrameView::performPostLayoutTasks()
RenderView* root = m_frame->contentRenderer();
root->updateWidgetPositions();
- if (m_widgetUpdateSet && m_nestedLayoutCount <= 1) {
- Vector<RenderPartObject*> objectVector;
- copyToVector(*m_widgetUpdateSet, objectVector);
- size_t size = objectVector.size();
- for (size_t i = 0; i < size; ++i) {
- RenderPartObject* object = objectVector[i];
- object->updateWidget(false);
-
- // updateWidget() can destroy the RenderPartObject, so we need to make sure it's
- // alive by checking if it's still in m_widgetUpdateSet.
- if (m_widgetUpdateSet->contains(object))
- object->updateWidgetPosition();
- }
- m_widgetUpdateSet->clear();
+
+ for (unsigned i = 0; i < maxUpdateWidgetsIterations; i++) {
+ if (updateWidgets())
+ break;
}
-
+
resumeScheduledEvents();
if (!root->printing()) {
@@ -995,7 +1140,7 @@ void FrameView::performPostLayoutTasks()
m_lastLayoutSize = currentSize;
m_lastZoomFactor = currentZoomFactor;
if (resized)
- m_frame->sendResizeEvent();
+ m_frame->eventHandler()->sendResizeEvent();
}
}
@@ -1025,7 +1170,7 @@ void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverf
scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow,
verticalOverflowChanged, verticalOverflow),
- EventTargetNodeCast(m_viewportRenderer->element()));
+ m_viewportRenderer->node());
}
}
@@ -1058,7 +1203,7 @@ IntRect FrameView::windowClipRect(bool clipToContents) const
// Set our clip rect to be our contents.
IntRect clipRect = contentsToWindow(visibleContentRect(!clipToContents));
- if (!m_frame || !m_frame->document() || !m_frame->document()->ownerElement())
+ if (!m_frame || !m_frame->document()->ownerElement())
return clipRect;
// Take our owner element and get the clip rect from the enclosing layer.
@@ -1100,7 +1245,7 @@ void FrameView::valueChanged(Scrollbar* bar)
IntSize offset = scrollOffset();
ScrollView::valueChanged(bar);
if (offset != scrollOffset())
- frame()->sendScrollEvent();
+ frame()->eventHandler()->sendScrollEvent();
}
void FrameView::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
@@ -1184,12 +1329,10 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
return;
Document* document = frame()->document();
- if (!document)
- return;
#ifndef NDEBUG
bool fillWithRed;
- if (document || document->printing())
+ if (document->printing())
fillWithRed = false; // Printing, don't fill with red (can't remember why).
else if (document->ownerElement())
fillWithRed = false; // Subframe, don't fill with red.
@@ -1226,8 +1369,9 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect)
if (m_paintRestriction == PaintRestrictionNone)
document->invalidateRenderedRectsForMarkersInRect(rect);
contentRenderer->layer()->paint(p, rect, m_paintRestriction, eltRenderer);
-
+
m_isPainting = false;
+ m_lastPaintTime = currentTime();
#if ENABLE(DASHBOARD_SUPPORT)
// Regions may have changed as a result of the visibility/z-index of element changing.
@@ -1275,4 +1419,60 @@ void FrameView::layoutIfNeededRecursive()
static_cast<FrameView*>(*current)->layoutIfNeededRecursive();
}
+void FrameView::forceLayout(bool allowSubtree)
+{
+ layout(allowSubtree);
+ // We cannot unschedule a pending relayout, since the force can be called with
+ // a tiny rectangle from a drawRect update. By unscheduling we in effect
+ // "validate" and stop the necessary full repaint from occurring. Basically any basic
+ // append/remove DHTML is broken by this call. For now, I have removed the optimization
+ // until we have a better invalidation stategy. -dwh
+ //unscheduleRelayout();
+}
+
+void FrameView::forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth, bool _adjustViewSize)
+{
+ // Dumping externalRepresentation(m_frame->renderer()).ascii() is a good trick to see
+ // the state of things before and after the layout
+ RenderView *root = toRenderView(m_frame->document()->renderer());
+ if (root) {
+ // This magic is basically copied from khtmlview::print
+ int pageW = (int)ceilf(minPageWidth);
+ root->setWidth(pageW);
+ root->setNeedsLayoutAndPrefWidthsRecalc();
+ forceLayout();
+
+ // If we don't fit in the minimum page width, we'll lay out again. If we don't fit in the
+ // maximum page width, we will lay out to the maximum page width and clip extra content.
+ // FIXME: We are assuming a shrink-to-fit printing implementation. A cropping
+ // implementation should not do this!
+ int rightmostPos = root->rightmostPosition();
+ if (rightmostPos > minPageWidth) {
+ pageW = std::min(rightmostPos, (int)ceilf(maxPageWidth));
+ root->setWidth(pageW);
+ root->setNeedsLayoutAndPrefWidthsRecalc();
+ forceLayout();
+ }
+ }
+
+ if (_adjustViewSize)
+ adjustViewSize();
+}
+
+void FrameView::adjustPageHeight(float *newBottom, float oldTop, float oldBottom, float /*bottomLimit*/)
+{
+ RenderView* root = m_frame->contentRenderer();
+ if (root) {
+ // Use a context with painting disabled.
+ GraphicsContext context((PlatformGraphicsContext*)0);
+ root->setTruncatedAt((int)floorf(oldBottom));
+ IntRect dirtyRect(0, (int)floorf(oldTop), root->docWidth(), (int)ceilf(oldBottom - oldTop));
+ root->layer()->paint(&context, dirtyRect);
+ *newBottom = root->bestTruncatedAt();
+ if (*newBottom == 0)
+ *newBottom = oldBottom;
+ } else
+ *newBottom = oldBottom;
+}
+
} // namespace WebCore
diff --git a/WebCore/page/FrameView.h b/WebCore/page/FrameView.h
index a1d514f..07295d3 100644
--- a/WebCore/page/FrameView.h
+++ b/WebCore/page/FrameView.h
@@ -35,7 +35,6 @@ namespace WebCore {
class Color;
class Event;
-class EventTargetNode;
class Frame;
class FrameViewPrivate;
class IntRect;
@@ -97,6 +96,18 @@ public:
bool needsFullRepaint() const { return m_doFullRepaint; }
+#if USE(ACCELERATED_COMPOSITING)
+ enum CompositingUpdate { NormalCompositingUpdate, ForcedCompositingUpdate };
+ void updateCompositingLayers(CompositingUpdate updateType = NormalCompositingUpdate);
+
+ // Called when changes to the GraphicsLayer hierarchy have to be synchronized with
+ // content rendered via the normal painting path.
+ void setNeedsOneShotDrawingSynchronization();
+#endif
+
+ void didMoveOnscreen();
+ void willMoveOffscreen();
+
void resetScrollbars();
void clear();
@@ -138,6 +149,8 @@ public:
void beginDeferredRepaints();
void endDeferredRepaints();
+ void checkStopDelayingDeferredRepaints();
+ void resetDeferredRepaintDelay();
#if ENABLE(DASHBOARD_SUPPORT)
void updateDashboardRegions();
@@ -146,7 +159,7 @@ public:
void restoreScrollbar();
- void scheduleEvent(PassRefPtr<Event>, PassRefPtr<EventTargetNode>);
+ void scheduleEvent(PassRefPtr<Event>, PassRefPtr<Node>);
void pauseScheduledEvents();
void resumeScheduledEvents();
void postLayoutTimerFired(Timer<FrameView>*);
@@ -168,6 +181,12 @@ public:
void setIsVisuallyNonEmpty() { m_isVisuallyNonEmpty = true; }
+ void forceLayout(bool allowSubtree = false);
+ void forceLayoutWithPageWidthRange(float minPageWidth, float maxPageWidth, bool adjustViewSize);
+
+ void adjustPageHeight(float* newBottom, float oldTop, float oldBottom, float bottomLimit);
+
+
private:
void reset();
void init();
@@ -186,7 +205,14 @@ private:
virtual void repaintContentRectangle(const IntRect&, bool immediate);
virtual void contentsResized() { setNeedsLayout(); }
virtual void visibleContentsResized() { layout(); }
+
+ void deferredRepaintTimerFired(Timer<FrameView>*);
+ void doDeferredRepaints();
+ void updateDeferredRepaintDelay();
+ double adjustedDeferredRepaintDelay() const;
+ bool updateWidgets();
+
static double sCurrentPaintTimeStamp; // used for detecting decoded resource thrash in the cache
unsigned m_refCount;
@@ -237,8 +263,10 @@ private:
unsigned m_deferringRepaints;
unsigned m_repaintCount;
- IntRect m_repaintRect;
Vector<IntRect> m_repaintRects;
+ Timer<FrameView> m_deferredRepaintTimer;
+ double m_deferredRepaintDelay;
+ double m_lastPaintTime;
bool m_shouldUpdateWhileOffscreen;
diff --git a/WebCore/page/Geolocation.cpp b/WebCore/page/Geolocation.cpp
index f82e95d..e2f31a1 100644
--- a/WebCore/page/Geolocation.cpp
+++ b/WebCore/page/Geolocation.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,8 +26,10 @@
#include "config.h"
#include "Geolocation.h"
+#include "Chrome.h"
#include "Document.h"
#include "Frame.h"
+#include "Page.h"
#include "PositionError.h"
namespace WebCore {
@@ -54,7 +56,11 @@ void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*)
Geolocation::Geolocation(Frame* frame)
: m_frame(frame)
, m_service(GeolocationService::create(this))
+ , m_allowGeolocation(Unknown)
+ , m_shouldClearCache(false)
{
+ if (!m_frame)
+ return;
ASSERT(m_frame->document());
m_frame->document()->setUsingGeolocation(true);
}
@@ -62,8 +68,6 @@ Geolocation::Geolocation(Frame* frame)
void Geolocation::disconnectFrame()
{
m_service->stopUpdating();
- if (m_frame->document())
- m_frame->document()->setUsingGeolocation(false);
m_frame = 0;
}
@@ -121,6 +125,18 @@ void Geolocation::resume()
m_service->resume();
}
+void Geolocation::setIsAllowed(bool allowed)
+{
+ m_allowGeolocation = allowed ? Yes : No;
+
+ if (isAllowed())
+ geolocationServicePositionChanged(m_service.get());
+ else {
+ WTF::RefPtr<WebCore::PositionError> error = WebCore::PositionError::create(PositionError::PERMISSION_DENIED, "User disallowed GeoLocation");
+ handleError(error.get());
+ }
+}
+
void Geolocation::sendErrorToOneShots(PositionError* error)
{
Vector<RefPtr<GeoNotifier> > copy;
@@ -199,10 +215,32 @@ void Geolocation::handleError(PositionError* error)
m_oneShots.clear();
}
+void Geolocation::requestPermission()
+{
+ if (m_allowGeolocation > Unknown)
+ return;
+
+ if (!m_frame)
+ return;
+
+ Page* page = m_frame->page();
+ if (!page)
+ return;
+
+ // Ask the chrome: it maintains the geolocation challenge policy itself.
+ page->chrome()->requestGeolocationPermissionForFrame(m_frame, this);
+
+ m_allowGeolocation = InProgress;
+}
+
void Geolocation::geolocationServicePositionChanged(GeolocationService* service)
{
ASSERT(service->lastPosition());
+ requestPermission();
+ if (!isAllowed())
+ return;
+
sendPositionToOneShots(service->lastPosition());
sendPositionToWatchers(service->lastPosition());
diff --git a/WebCore/page/Geolocation.h b/WebCore/page/Geolocation.h
index 572cbd8..a14fc4b 100644
--- a/WebCore/page/Geolocation.h
+++ b/WebCore/page/Geolocation.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -60,6 +60,12 @@ public:
void suspend();
void resume();
+
+ void setIsAllowed(bool);
+ bool isAllowed() const { return m_allowGeolocation == Yes; }
+
+ void setShouldClearCache(bool shouldClearCache) { m_shouldClearCache = shouldClearCache; }
+ bool shouldClearCache() const { return m_shouldClearCache; }
private:
Geolocation(Frame*);
@@ -77,7 +83,7 @@ private:
private:
GeoNotifier(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PositionOptions*);
};
-
+
bool hasListeners() const { return !m_oneShots.isEmpty() || !m_watchers.isEmpty(); }
void sendErrorToOneShots(PositionError*);
@@ -86,10 +92,13 @@ private:
void sendPositionToWatchers(Geoposition*);
void handleError(PositionError*);
-
+
+ void requestPermission();
+
+ // GeolocationServiceClient
virtual void geolocationServicePositionChanged(GeolocationService*);
virtual void geolocationServiceErrorOccurred(GeolocationService*);
-
+
typedef HashSet<RefPtr<GeoNotifier> > GeoNotifierSet;
typedef HashMap<int, RefPtr<GeoNotifier> > GeoNotifierMap;
@@ -97,6 +106,14 @@ private:
GeoNotifierMap m_watchers;
Frame* m_frame;
OwnPtr<GeolocationService> m_service;
+
+ enum {
+ Unknown,
+ InProgress,
+ Yes,
+ No
+ } m_allowGeolocation;
+ bool m_shouldClearCache;
};
} // namespace WebCore
diff --git a/WebCore/page/Geoposition.cpp b/WebCore/page/Geoposition.cpp
index 1792a1f..8f7a5c8 100644
--- a/WebCore/page/Geoposition.cpp
+++ b/WebCore/page/Geoposition.cpp
@@ -30,9 +30,7 @@ namespace WebCore {
String Geoposition::toString() const
{
- return String::format("position(%.6lg, %.6lg, %.6lg, %.6lg, %.6lg, %.6lg, %.6lg, %.lld)",
- m_latitude, m_longitude, m_altitude, m_accuracy,
- m_altitudeAccuracy, m_heading, m_speed, m_timestamp);
+ return "position(" + m_coordinates->toString() + String::format(", %.lld)", m_timestamp);
}
} // namespace WebCore
diff --git a/WebCore/page/Geoposition.h b/WebCore/page/Geoposition.h
index 9ce50e5..505e8b3 100644
--- a/WebCore/page/Geoposition.h
+++ b/WebCore/page/Geoposition.h
@@ -26,6 +26,7 @@
#ifndef Geoposition_h
#define Geoposition_h
+#include "Coordinates.h"
#include "Event.h"
#include "PlatformString.h"
#include <wtf/RefCounted.h>
@@ -36,39 +37,21 @@ typedef int ExceptionCode;
class Geoposition : public RefCounted<Geoposition> {
public:
- static PassRefPtr<Geoposition> create(double latitude, double longitude, double altitude, double accuracy, double altitudeAccuracy, double heading, double speed, DOMTimeStamp timestamp) { return adoptRef(new Geoposition(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed, timestamp)); }
+ static PassRefPtr<Geoposition> create(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp) { return adoptRef(new Geoposition(coordinates, timestamp)); }
- double latitude() const { return m_latitude; }
- double longitude() const { return m_longitude; }
- double altitude() const { return m_altitude; }
- double accuracy() const { return m_accuracy; }
- double altitudeAccuracy() const { return m_altitudeAccuracy; }
- double heading() const { return m_heading; }
- double speed() const { return m_speed; }
DOMTimeStamp timestamp() const { return m_timestamp; }
-
+ Coordinates* coords() const { return m_coordinates.get(); }
+
String toString() const;
private:
- Geoposition(double latitude, double longitude, double altitude, double accuracy, double altitudeAccuracy, double heading, double speed, DOMTimeStamp timestamp)
- : m_latitude(latitude)
- , m_longitude(longitude)
- , m_altitude(altitude)
- , m_accuracy(accuracy)
- , m_altitudeAccuracy(altitudeAccuracy)
- , m_heading(heading)
- , m_speed(speed)
+ Geoposition(PassRefPtr<Coordinates> coordinates, DOMTimeStamp timestamp)
+ : m_coordinates(coordinates)
, m_timestamp(timestamp)
{
}
- double m_latitude;
- double m_longitude;
- double m_altitude;
- double m_accuracy;
- double m_altitudeAccuracy;
- double m_heading;
- double m_speed;
+ RefPtr<Coordinates> m_coordinates;
DOMTimeStamp m_timestamp;
};
diff --git a/WebCore/page/Geoposition.idl b/WebCore/page/Geoposition.idl
index 554bb30..2bcd40d 100644
--- a/WebCore/page/Geoposition.idl
+++ b/WebCore/page/Geoposition.idl
@@ -26,13 +26,7 @@
module core {
interface Geoposition {
- readonly attribute double latitude;
- readonly attribute double longitude;
- readonly attribute double altitude;
- readonly attribute double accuracy;
- readonly attribute double altitudeAccuracy;
- readonly attribute double heading;
- readonly attribute double speed;
+ readonly attribute Coordinates coords;
readonly attribute DOMTimeStamp timestamp;
#if defined(LANGUAGE_JAVASCRIPT)
diff --git a/WebCore/page/History.idl b/WebCore/page/History.idl
index e86cf92..c8cddae 100644
--- a/WebCore/page/History.idl
+++ b/WebCore/page/History.idl
@@ -26,6 +26,9 @@
module window {
interface [
+#if defined(V8_BINDING)
+ CheckDomainSecurity,
+#endif
CustomGetOwnPropertySlot,
CustomPutFunction,
CustomDeleteProperty,
@@ -33,9 +36,9 @@ module window {
] History {
readonly attribute unsigned long length;
- void back();
- void forward();
- void go(in long distance);
+ [DoNotCheckDomainSecurity] void back();
+ [DoNotCheckDomainSecurity] void forward();
+ [DoNotCheckDomainSecurity] void go(in long distance);
};
}
diff --git a/WebCore/page/Location.cpp b/WebCore/page/Location.cpp
index 454aa78..ba28086 100644
--- a/WebCore/page/Location.cpp
+++ b/WebCore/page/Location.cpp
@@ -111,7 +111,8 @@ String Location::search() const
if (!m_frame)
return String();
- return url().query();
+ const KURL& url = this->url();
+ return url.query().isEmpty() ? "" : "?" + url.query();
}
String Location::hash() const
@@ -120,7 +121,7 @@ String Location::hash() const
return String();
const KURL& url = this->url();
- return url.ref().isNull() ? "" : "#" + url.ref();
+ return url.ref().isEmpty() ? "" : "#" + url.ref();
}
String Location::toString() const
diff --git a/WebCore/page/Location.idl b/WebCore/page/Location.idl
index 91822ab..20f8bbd 100644
--- a/WebCore/page/Location.idl
+++ b/WebCore/page/Location.idl
@@ -29,16 +29,19 @@
module window {
interface [
+#if defined(V8_BINDING)
+ CheckDomainSecurity,
+#endif
CustomGetOwnPropertySlot,
CustomPutFunction,
CustomDeleteProperty,
CustomGetPropertyNames
] Location {
- attribute [CustomSetter] DOMString href;
+ attribute [DoNotCheckDomainSecurityOnSet, CustomSetter, V8DisallowShadowing] DOMString href;
- [Custom] void assign(in DOMString url);
- [Custom] void replace(in DOMString url);
- [Custom] void reload();
+ [Custom, V8OnInstance] void assign(in DOMString url);
+ [Custom, V8OnInstance] void replace(in DOMString url);
+ [Custom, V8OnInstance] void reload();
// URI decomposition attributes
attribute [CustomSetter] DOMString protocol;
@@ -50,7 +53,10 @@ module window {
attribute [CustomSetter] DOMString hash;
#if defined(LANGUAGE_JAVASCRIPT)
- [DontEnum, Custom] DOMString toString();
+ [DontEnum, Custom, V8OnInstance, V8ReadOnly] DOMString toString();
+#endif
+#if defined(V8_BINDING)
+ [DontEnum, Custom, V8OnInstance, V8ReadOnly] DOMObject valueOf();
#endif
};
diff --git a/WebCore/page/Navigator.cpp b/WebCore/page/Navigator.cpp
index 429ec00..dd4d27d 100644
--- a/WebCore/page/Navigator.cpp
+++ b/WebCore/page/Navigator.cpp
@@ -102,7 +102,13 @@ String Navigator::userAgent() const
{
if (!m_frame)
return String();
- return m_frame->loader()->userAgent(m_frame->document() ? m_frame->document()->url() : KURL());
+
+ // If the frame is already detached, FrameLoader::userAgent may malfunction, because it calls a client method
+ // that uses frame's WebView (at least, in Mac WebKit).
+ if (!m_frame->page())
+ return String();
+
+ return m_frame->loader()->userAgent(m_frame->document()->url());
}
PluginArray* Navigator::plugins() const
@@ -121,6 +127,9 @@ MimeTypeArray* Navigator::mimeTypes() const
bool Navigator::cookieEnabled() const
{
+ if (!m_frame)
+ return false;
+
if (m_frame->page() && !m_frame->page()->cookieEnabled())
return false;
@@ -129,8 +138,9 @@ bool Navigator::cookieEnabled() const
bool Navigator::javaEnabled() const
{
- if (!m_frame)
+ if (!m_frame || !m_frame->settings())
return false;
+
return m_frame->settings()->isJavaEnabled();
}
diff --git a/WebCore/page/NavigatorBase.cpp b/WebCore/page/NavigatorBase.cpp
index 27c9fdd..5138b0f 100644
--- a/WebCore/page/NavigatorBase.cpp
+++ b/WebCore/page/NavigatorBase.cpp
@@ -31,9 +31,9 @@
#include "PlatformString.h"
#ifndef WEBCORE_NAVIGATOR_PLATFORM
-#if PLATFORM(MAC) && PLATFORM(PPC)
+#if PLATFORM(MAC) && (PLATFORM(PPC) || PLATFORM(PPC64))
#define WEBCORE_NAVIGATOR_PLATFORM "MacPPC"
-#elif PLATFORM(MAC) && PLATFORM(X86)
+#elif PLATFORM(MAC) && (PLATFORM(X86) || PLATFORM(X86_64))
#define WEBCORE_NAVIGATOR_PLATFORM "MacIntel"
#elif PLATFORM(WIN_OS)
#define WEBCORE_NAVIGATOR_PLATFORM "Win32"
diff --git a/WebCore/page/Page.cpp b/WebCore/page/Page.cpp
index 460183a..457bcde 100644
--- a/WebCore/page/Page.cpp
+++ b/WebCore/page/Page.cpp
@@ -93,11 +93,8 @@ static void networkStateChanged()
for (unsigned i = 0; i < frames.size(); i++) {
Document* document = frames[i]->document();
- if (!document)
- continue;
-
// If the document does not have a body the event should be dispatched to the document
- EventTargetNode* eventTarget = document->body();
+ Node* eventTarget = document->body();
if (!eventTarget)
eventTarget = document;
@@ -111,7 +108,7 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi
, m_dragController(new DragController(this, dragClient))
, m_focusController(new FocusController(this))
, m_contextMenuController(new ContextMenuController(this, contextMenuClient))
- , m_inspectorController(new InspectorController(this, inspectorClient))
+ , m_inspectorController(InspectorController::create(this, inspectorClient))
, m_settings(new Settings(this))
, m_progress(new ProgressTracker)
, m_backForwardList(BackForwardList::create(this))
@@ -157,11 +154,9 @@ Page::~Page()
setGroupName(String());
allPages->remove(this);
- for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
- if (frame->document())
- frame->document()->documentWillBecomeInactive();
+ for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext())
frame->pageDestroyed();
- }
+
m_editorClient->pageDestroyed();
if (m_parentInspectorController)
m_parentInspectorController->pageDestroyed();
@@ -233,7 +228,7 @@ void Page::setGroupName(const String& name)
}
if (name.isEmpty())
- m_group = 0;
+ m_group = m_singlePageGroup.get();
else {
m_singlePageGroup.clear();
m_group = PageGroup::pageGroup(name);
@@ -358,13 +353,12 @@ void Page::unmarkAllTextMatches()
Frame* frame = mainFrame();
do {
- if (Document* document = frame->document())
- document->removeMarkers(DocumentMarker::TextMatch);
+ frame->document()->removeMarkers(DocumentMarker::TextMatch);
frame = incrementFrame(frame, true, false);
} while (frame);
}
-const Selection& Page::selection() const
+const VisibleSelection& Page::selection() const
{
return focusController()->focusedOrMainFrame()->selection()->selection();
}
@@ -404,8 +398,23 @@ void Page::setMediaVolume(float volume)
m_mediaVolume = volume;
for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
- if (frame->document())
- frame->document()->mediaVolumeDidChange();
+ frame->document()->mediaVolumeDidChange();
+ }
+}
+
+void Page::didMoveOnscreen()
+{
+ for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+ if (frame->view())
+ frame->view()->didMoveOnscreen();
+ }
+}
+
+void Page::willMoveOffscreen()
+{
+ for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+ if (frame->view())
+ frame->view()->willMoveOffscreen();
}
}
@@ -461,7 +470,9 @@ const String& Page::userStyleSheet() const
if (!data)
return m_userStyleSheet;
- m_userStyleSheet = TextResourceDecoder::create("text/css")->decode(data->data(), data->size());
+ RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/css");
+ m_userStyleSheet = decoder->decode(data->data(), data->size());
+ m_userStyleSheet += decoder->flush();
return m_userStyleSheet;
}
diff --git a/WebCore/page/Page.h b/WebCore/page/Page.h
index aea16a2..f140783 100644
--- a/WebCore/page/Page.h
+++ b/WebCore/page/Page.h
@@ -60,7 +60,7 @@ namespace WebCore {
class PageGroup;
class PluginData;
class ProgressTracker;
- class Selection;
+ class VisibleSelection;
class SelectionController;
#if ENABLE(DOM_STORAGE)
class SessionStorage;
@@ -137,7 +137,7 @@ namespace WebCore {
OwnPtr<SchedulePairHashSet> m_scheduledRunLoopPairs;
#endif
- const Selection& selection() const;
+ const VisibleSelection& selection() const;
void setDefersLoading(bool);
bool defersLoading() const { return m_defersLoading; }
@@ -153,6 +153,10 @@ namespace WebCore {
float mediaVolume() const { return m_mediaVolume; }
void setMediaVolume(float volume);
+ // Notifications when the Page starts and stops being presented via a native window.
+ void didMoveOnscreen();
+ void willMoveOffscreen();
+
void userStyleSheetLocationChanged();
const String& userStyleSheet() const;
@@ -204,7 +208,7 @@ namespace WebCore {
OwnPtr<DragController> m_dragController;
OwnPtr<FocusController> m_focusController;
OwnPtr<ContextMenuController> m_contextMenuController;
- OwnPtr<InspectorController> m_inspectorController;
+ RefPtr<InspectorController> m_inspectorController;
OwnPtr<Settings> m_settings;
OwnPtr<ProgressTracker> m_progress;
diff --git a/WebCore/page/PositionOptions.h b/WebCore/page/PositionOptions.h
index dc9c167..10845d3 100644
--- a/WebCore/page/PositionOptions.h
+++ b/WebCore/page/PositionOptions.h
@@ -33,22 +33,26 @@ namespace WebCore {
class PositionOptions : public RefCounted<PositionOptions> {
public:
- static PassRefPtr<PositionOptions> create(bool highAccuracy, unsigned timeout) { return adoptRef(new PositionOptions(highAccuracy, timeout)); }
+ static PassRefPtr<PositionOptions> create(bool highAccuracy, unsigned timeout, unsigned maximumAge) { return adoptRef(new PositionOptions(highAccuracy, timeout, maximumAge)); }
bool enableHighAccuracy() const { return m_highAccuracy; }
void setEnableHighAccuracy(bool enable) { m_highAccuracy = enable; }
unsigned timeout() const { return m_timeout; }
void setTimeout(unsigned t) { m_timeout = t; }
+ unsigned maximumAge() const { return m_maximumAge; }
+ void setMaximumAge(unsigned a) { m_maximumAge = a; }
private:
- PositionOptions(bool highAccuracy, unsigned timeout)
+ PositionOptions(bool highAccuracy, unsigned timeout, unsigned maximumAge)
: m_highAccuracy(highAccuracy)
, m_timeout(timeout)
+ , m_maximumAge(maximumAge)
{
}
bool m_highAccuracy;
unsigned m_timeout;
+ unsigned m_maximumAge;
};
} // namespace WebCore
diff --git a/WebCore/page/PrintContext.cpp b/WebCore/page/PrintContext.cpp
index 79672a3..b83d714 100644
--- a/WebCore/page/PrintContext.cpp
+++ b/WebCore/page/PrintContext.cpp
@@ -85,7 +85,7 @@ void PrintContext::computePageRects(const FloatRect& printRect, float headerHeig
float printedPagesHeight = 0.0;
do {
float proposedBottom = std::min(docHeight, printedPagesHeight + pageHeight);
- m_frame->adjustPageHeight(&proposedBottom, printedPagesHeight, proposedBottom, printedPagesHeight);
+ m_frame->view()->adjustPageHeight(&proposedBottom, printedPagesHeight, proposedBottom, printedPagesHeight);
currPageHeight = max(1.0f, proposedBottom - printedPagesHeight);
m_pageRects.append(IntRect(0, (int)printedPagesHeight, (int)currPageWidth, (int)currPageHeight));
diff --git a/WebCore/page/SecurityOrigin.cpp b/WebCore/page/SecurityOrigin.cpp
index fd8144f..a1863c9 100644
--- a/WebCore/page/SecurityOrigin.cpp
+++ b/WebCore/page/SecurityOrigin.cpp
@@ -58,14 +58,15 @@ SecurityOrigin::SecurityOrigin(const KURL& url)
, m_host(url.host().isNull() ? "" : url.host().lower())
, m_port(url.port())
, m_noAccess(false)
+ , m_universalAccess(false)
, m_domainWasSetInDOM(false)
{
// These protocols do not create security origins; the owner frame provides the origin
if (m_protocol == "about" || m_protocol == "javascript")
m_protocol = "";
- // data: URLs are not allowed access to anything other than themselves.
- if (m_protocol == "data")
+ // Some URLs are not allowed access to anything other than themselves.
+ if (FrameLoader::shouldTreatURLSchemeAsNoAccess(m_protocol))
m_noAccess = true;
// document.domain starts as m_host, but can be set by the DOM.
@@ -84,6 +85,7 @@ SecurityOrigin::SecurityOrigin(const SecurityOrigin* other)
, m_domain(other->m_domain.copy())
, m_port(other->m_port)
, m_noAccess(other->m_noAccess)
+ , m_universalAccess(other->m_universalAccess)
, m_domainWasSetInDOM(other->m_domainWasSetInDOM)
, m_canLoadLocalResources(other->m_canLoadLocalResources)
{
@@ -119,7 +121,7 @@ void SecurityOrigin::setDomainFromDOM(const String& newDomain)
bool SecurityOrigin::canAccess(const SecurityOrigin* other) const
{
- if (isLocal())
+ if (m_universalAccess)
return true;
if (m_noAccess || other->m_noAccess)
@@ -160,7 +162,7 @@ bool SecurityOrigin::canAccess(const SecurityOrigin* other) const
bool SecurityOrigin::canRequest(const KURL& url) const
{
- if (isLocal())
+ if (m_universalAccess)
return true;
if (m_noAccess)
@@ -184,9 +186,14 @@ void SecurityOrigin::grantLoadLocalResources()
m_canLoadLocalResources = true;
}
+void SecurityOrigin::grantUniversalAccess()
+{
+ m_universalAccess = true;
+}
+
bool SecurityOrigin::isLocal() const
{
- return FrameLoader::shouldTreatSchemeAsLocal(m_protocol);
+ return FrameLoader::shouldTreatURLSchemeAsLocal(m_protocol);
}
bool SecurityOrigin::isSecureTransitionTo(const KURL& url) const
@@ -211,7 +218,7 @@ String SecurityOrigin::toString() const
return String("file://");
Vector<UChar> result;
- result.reserveCapacity(m_protocol.length() + m_host.length() + 10);
+ result.reserveInitialCapacity(m_protocol.length() + m_host.length() + 10);
append(result, m_protocol);
append(result, "://");
append(result, m_host);
@@ -259,7 +266,7 @@ PassRefPtr<SecurityOrigin> SecurityOrigin::createFromDatabaseIdentifier(const St
// Split out the 3 sections of data
String protocol = databaseIdentifier.substring(0, separator1);
String host = databaseIdentifier.substring(separator1 + 1, separator2 - separator1 - 1);
- return create(KURL(protocol + "://" + host + ":" + String::number(port)));
+ return create(KURL(KURL(), protocol + "://" + host + ":" + String::number(port)));
}
String SecurityOrigin::databaseIdentifier() const
diff --git a/WebCore/page/SecurityOrigin.h b/WebCore/page/SecurityOrigin.h
index 1f2624e..96f85df 100644
--- a/WebCore/page/SecurityOrigin.h
+++ b/WebCore/page/SecurityOrigin.h
@@ -90,6 +90,11 @@ namespace WebCore {
// with older versions of WebKit.
void grantLoadLocalResources();
+ // Explicitly grant the ability to access very other SecurityOrigin.
+ //
+ // WARNING: This is an extremely powerful ability. Use with caution!
+ void grantUniversalAccess();
+
bool isSecureTransitionTo(const KURL&) const;
// The local SecurityOrigin is the most privileged SecurityOrigin.
@@ -132,6 +137,7 @@ namespace WebCore {
String m_domain;
unsigned short m_port;
bool m_noAccess;
+ bool m_universalAccess;
bool m_domainWasSetInDOM;
bool m_canLoadLocalResources;
};
diff --git a/WebCore/page/Settings.cpp b/WebCore/page/Settings.cpp
index 8c9bb44..1815535 100644
--- a/WebCore/page/Settings.cpp
+++ b/WebCore/page/Settings.cpp
@@ -72,6 +72,8 @@ Settings::Settings(Page* page)
, m_databasesEnabled(false)
, m_localStorageEnabled(false)
, m_isJavaScriptEnabled(false)
+ , m_isWebSecurityEnabled(true)
+ , m_allowUniversalAccessFromFileURLs(true)
, m_javaScriptCanOpenWindowsAutomatically(false)
, m_shouldPrintBackgrounds(false)
, m_textAreasAreResizable(false)
@@ -80,6 +82,8 @@ Settings::Settings(Page* page)
#endif
, m_needsAdobeFrameReloadingQuirk(false)
, m_needsKeyboardEventDisambiguationQuirks(false)
+ , m_needsLeopardMailQuirks(false)
+ , m_needsTigerMailQuirks(false)
, m_isDOMPasteAllowed(false)
, m_shrinksStandaloneImagesToFit(true)
, m_usesPageCache(false)
@@ -92,12 +96,12 @@ Settings::Settings(Page* page)
, m_webArchiveDebugModeEnabled(false)
, m_inApplicationChromeMode(false)
, m_offlineWebApplicationCacheEnabled(false)
- , m_rangeMutationDisabledForOldAppleMail(false)
, m_shouldPaintCustomScrollbars(false)
, m_zoomsTextOnly(false)
, m_enforceCSSMIMETypeInStrictMode(true)
+ , m_usesEncodingDetector(false)
, m_maximumDecodedImageSize(std::numeric_limits<size_t>::max())
- , m_needsIChatMemoryCacheCallsQuirk(false)
+ , m_allowScriptsToCloseWindows(false)
{
// A Frame may not have been created yet, so we initialize the AtomicString
// hash before trying to use it.
@@ -214,6 +218,16 @@ void Settings::setJavaScriptEnabled(bool isJavaScriptEnabled)
m_isJavaScriptEnabled = isJavaScriptEnabled;
}
+void Settings::setWebSecurityEnabled(bool isWebSecurityEnabled)
+{
+ m_isWebSecurityEnabled = isWebSecurityEnabled;
+}
+
+void Settings::setAllowUniversalAccessFromFileURLs(bool allowUniversalAccessFromFileURLs)
+{
+ m_allowUniversalAccessFromFileURLs = allowUniversalAccessFromFileURLs;
+}
+
void Settings::setJavaEnabled(bool isJavaEnabled)
{
m_isJavaEnabled = isJavaEnabled;
@@ -313,6 +327,16 @@ void Settings::setNeedsKeyboardEventDisambiguationQuirks(bool needsQuirks)
m_needsKeyboardEventDisambiguationQuirks = needsQuirks;
}
+void Settings::setNeedsLeopardMailQuirks(bool needsQuirks)
+{
+ m_needsLeopardMailQuirks = needsQuirks;
+}
+
+void Settings::setNeedsTigerMailQuirks(bool needsQuirks)
+{
+ m_needsTigerMailQuirks = needsQuirks;
+}
+
void Settings::setDOMPasteAllowed(bool DOMPasteAllowed)
{
m_isDOMPasteAllowed = DOMPasteAllowed;
@@ -483,11 +507,6 @@ void Settings::setLocalStorageDatabasePath(const String& path)
m_localStorageDatabasePath = path;
}
-void Settings::disableRangeMutationForOldAppleMail(bool disable)
-{
- m_rangeMutationDisabledForOldAppleMail = disable;
-}
-
void Settings::setApplicationChromeMode(bool mode)
{
m_inApplicationChromeMode = mode;
@@ -524,9 +543,14 @@ void Settings::setShouldPaintNativeControls(bool shouldPaintNativeControls)
}
#endif
-void Settings::setNeedsIChatMemoryCacheCallsQuirk(bool needsIChatMemoryCacheCallsQuirk)
+void Settings::setUsesEncodingDetector(bool usesEncodingDetector)
+{
+ m_usesEncodingDetector = usesEncodingDetector;
+}
+
+void Settings::setAllowScriptsToCloseWindows(bool allowScriptsToCloseWindows)
{
- m_needsIChatMemoryCacheCallsQuirk = needsIChatMemoryCacheCallsQuirk;
+ m_allowScriptsToCloseWindows = allowScriptsToCloseWindows;
}
} // namespace WebCore
diff --git a/WebCore/page/Settings.h b/WebCore/page/Settings.h
index b9b888f..925324f 100644
--- a/WebCore/page/Settings.h
+++ b/WebCore/page/Settings.h
@@ -112,6 +112,12 @@ namespace WebCore {
void setJavaScriptEnabled(bool);
bool isJavaScriptEnabled() const { return m_isJavaScriptEnabled; }
+ void setWebSecurityEnabled(bool);
+ bool isWebSecurityEnabled() const { return m_isWebSecurityEnabled; }
+
+ void setAllowUniversalAccessFromFileURLs(bool);
+ bool allowUniversalAccessFromFileURLs() const { return m_allowUniversalAccessFromFileURLs; }
+
void setJavaScriptCanOpenWindowsAutomatically(bool);
bool JavaScriptCanOpenWindowsAutomatically() const { return m_javaScriptCanOpenWindowsAutomatically; }
@@ -137,6 +143,9 @@ namespace WebCore {
void setDefaultTextEncodingName(const String&);
const String& defaultTextEncodingName() const { return m_defaultTextEncodingName; }
+
+ void setUsesEncodingDetector(bool);
+ bool usesEncodingDetector() const { return m_usesEncodingDetector; }
void setUserStyleSheetLocation(const KURL&);
const KURL& userStyleSheetLocation() const { return m_userStyleSheetLocation; }
@@ -164,6 +173,12 @@ namespace WebCore {
void setNeedsKeyboardEventDisambiguationQuirks(bool);
bool needsKeyboardEventDisambiguationQuirks() const { return m_needsKeyboardEventDisambiguationQuirks; }
+ void setNeedsLeopardMailQuirks(bool);
+ bool needsLeopardMailQuirks() const { return m_needsLeopardMailQuirks; }
+
+ void setNeedsTigerMailQuirks(bool);
+ bool needsTigerMailQuirks() const { return m_needsTigerMailQuirks; }
+
void setDOMPasteAllowed(bool);
bool isDOMPasteAllowed() const { return m_isDOMPasteAllowed; }
@@ -218,9 +233,6 @@ namespace WebCore {
void setLocalStorageDatabasePath(const String&);
const String& localStorageDatabasePath() const { return m_localStorageDatabasePath; }
- void disableRangeMutationForOldAppleMail(bool);
- bool rangeMutationDisabledForOldAppleMail() const { return m_rangeMutationDisabledForOldAppleMail; }
-
void setApplicationChromeMode(bool);
bool inApplicationChromeMode() const { return m_inApplicationChromeMode; }
@@ -245,8 +257,8 @@ namespace WebCore {
static bool shouldPaintNativeControls() { return gShouldPaintNativeControls; }
#endif
- void setNeedsIChatMemoryCacheCallsQuirk(bool);
- bool needsIChatMemoryCacheCallsQuirk() const { return m_needsIChatMemoryCacheCallsQuirk; }
+ void setAllowScriptsToCloseWindows(bool);
+ bool allowScriptsToCloseWindows() const { return m_allowScriptsToCloseWindows; }
private:
Page* m_page;
@@ -311,6 +323,8 @@ namespace WebCore {
bool m_databasesEnabled : 1;
bool m_localStorageEnabled : 1;
bool m_isJavaScriptEnabled : 1;
+ bool m_isWebSecurityEnabled : 1;
+ bool m_allowUniversalAccessFromFileURLs: 1;
bool m_javaScriptCanOpenWindowsAutomatically : 1;
bool m_shouldPrintBackgrounds : 1;
bool m_textAreasAreResizable : 1;
@@ -319,6 +333,8 @@ namespace WebCore {
#endif
bool m_needsAdobeFrameReloadingQuirk : 1;
bool m_needsKeyboardEventDisambiguationQuirks : 1;
+ bool m_needsLeopardMailQuirks : 1;
+ bool m_needsTigerMailQuirks : 1;
bool m_isDOMPasteAllowed : 1;
bool m_shrinksStandaloneImagesToFit : 1;
bool m_usesPageCache: 1;
@@ -331,12 +347,12 @@ namespace WebCore {
bool m_webArchiveDebugModeEnabled : 1;
bool m_inApplicationChromeMode : 1;
bool m_offlineWebApplicationCacheEnabled : 1;
- bool m_rangeMutationDisabledForOldAppleMail : 1;
bool m_shouldPaintCustomScrollbars : 1;
bool m_zoomsTextOnly : 1;
bool m_enforceCSSMIMETypeInStrictMode : 1;
+ bool m_usesEncodingDetector : 1;
size_t m_maximumDecodedImageSize;
- bool m_needsIChatMemoryCacheCallsQuirk : 1;
+ bool m_allowScriptsToCloseWindows : 1;
#if USE(SAFARI_THEME)
static bool gShouldPaintNativeControls;
diff --git a/WebCore/page/WebKitPoint.h b/WebCore/page/WebKitPoint.h
new file mode 100644
index 0000000..501b17f
--- /dev/null
+++ b/WebCore/page/WebKitPoint.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+#ifndef WebKitPoint_h
+#define WebKitPoint_h
+
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+ class WebKitPoint : public RefCounted<WebKitPoint> {
+ public:
+
+ static PassRefPtr<WebKitPoint> create()
+ {
+ return adoptRef(new WebKitPoint());
+ }
+ static PassRefPtr<WebKitPoint> create(float x, float y)
+ {
+ return adoptRef(new WebKitPoint(x, y));
+ }
+
+ float x() const { return m_x; }
+ float y() const { return m_y; }
+
+ void setX(float x) { m_x = x; }
+ void setY(float y) { m_y = y; }
+
+ private:
+ WebKitPoint(float x=0, float y=0)
+ : m_x(x)
+ , m_y(y)
+ {
+ }
+
+ float m_x, m_y;
+ };
+
+} // namespace WebCore
+
+#endif // WebKitPoint_h
diff --git a/WebCore/page/WebKitPoint.idl b/WebCore/page/WebKitPoint.idl
new file mode 100644
index 0000000..1eefbc3
--- /dev/null
+++ b/WebCore/page/WebKitPoint.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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.
+ */
+
+module window {
+
+ interface WebKitPoint {
+ attribute float x;
+ attribute float y;
+ };
+
+}
diff --git a/WebCore/page/android/InspectorControllerAndroid.cpp b/WebCore/page/android/InspectorControllerAndroid.cpp
index d6222d7..8763df1 100644
--- a/WebCore/page/android/InspectorControllerAndroid.cpp
+++ b/WebCore/page/android/InspectorControllerAndroid.cpp
@@ -106,4 +106,6 @@ void InspectorController::failedToParseSource(JSC::ExecState* exec, const JSC::S
void InspectorController::didParseSource(JSC::ExecState* exec, const JSC::SourceCode& source) {}
void InspectorController::didPause() {}
+void InspectorController::scriptImported(unsigned long identifier, const JSC::UString& sourceString) {}
+void InspectorController::startUserInitiatedProfiling(Timer<InspectorController>*) {}
} // namespace WebCore
diff --git a/WebCore/page/animation/AnimationBase.cpp b/WebCore/page/animation/AnimationBase.cpp
index 3e43f66..e500fe4 100644
--- a/WebCore/page/animation/AnimationBase.cpp
+++ b/WebCore/page/animation/AnimationBase.cpp
@@ -29,7 +29,7 @@
#include "config.h"
#include "AnimationBase.h"
-#include "AnimationController.h"
+#include "AnimationControllerPrivate.h"
#include "CSSMutableStyleDeclaration.h"
#include "CSSPropertyLonghand.h"
#include "CSSPropertyNames.h"
@@ -43,10 +43,15 @@
#include "ImplicitAnimation.h"
#include "KeyframeAnimation.h"
#include "MatrixTransformOperation.h"
-#include "RenderObject.h"
+#include "Matrix3DTransformOperation.h"
+#include "RenderBox.h"
#include "RenderStyle.h"
#include "UnitBezier.h"
+#include <algorithm>
+
+using namespace std;
+
namespace WebCore {
// The epsilon value we pass to UnitBezier::solve given that the animation is going to run over |dur| seconds. The longer the
@@ -143,7 +148,7 @@ static inline TransformOperations blendFunc(const AnimationBase* anim, const Tra
toT.blend(fromT, progress);
// Append the result
- result.operations().append(MatrixTransformOperation::create(toT.a(), toT.b(), toT.c(), toT.d(), toT.e(), toT.f()));
+ result.operations().append(Matrix3DTransformOperation::create(toT));
}
return result;
}
@@ -180,6 +185,10 @@ public:
int property() const { return m_prop; }
+#if USE(ACCELERATED_COMPOSITING)
+ virtual bool animationIsAccelerated() const { return false; }
+#endif
+
private:
int m_prop;
};
@@ -197,7 +206,7 @@ public:
{
// If the style pointers are the same, don't bother doing the test.
// If either is null, return false. If both are null, return true.
- if (!a && !b || a == b)
+ if ((!a && !b) || a == b)
return true;
if (!a || !b)
return false;
@@ -226,6 +235,41 @@ protected:
void (RenderStyle::*m_setter)(T);
};
+#if USE(ACCELERATED_COMPOSITING)
+class PropertyWrapperAcceleratedOpacity : public PropertyWrapper<float> {
+public:
+ PropertyWrapperAcceleratedOpacity()
+ : PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity)
+ {
+ }
+
+ virtual bool animationIsAccelerated() const { return true; }
+
+ virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
+ {
+ float fromOpacity = a->opacity();
+
+ // This makes sure we put the object being animated into a RenderLayer during the animation
+ dst->setOpacity(blendFunc(anim, (fromOpacity == 1) ? 0.999999f : fromOpacity, b->opacity(), progress));
+ }
+};
+
+class PropertyWrapperAcceleratedTransform : public PropertyWrapper<const TransformOperations&> {
+public:
+ PropertyWrapperAcceleratedTransform()
+ : PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform)
+ {
+ }
+
+ virtual bool animationIsAccelerated() const { return true; }
+
+ virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
+ {
+ dst->setTransform(blendFunc(anim, a->transform(), b->transform(), progress));
+ }
+};
+#endif // USE(ACCELERATED_COMPOSITING)
+
class PropertyWrapperShadow : public PropertyWrapperGetter<ShadowData*> {
public:
PropertyWrapperShadow(int prop, ShadowData* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(ShadowData*, bool))
@@ -239,7 +283,7 @@ public:
ShadowData* shadowA = (a->*m_getter)();
ShadowData* shadowB = (b->*m_getter)();
- if (!shadowA && shadowB || shadowA && !shadowB)
+ if ((!shadowA && shadowB) || (shadowA && !shadowB))
return false;
if (shadowA && shadowB && (*shadowA != *shadowB))
return false;
@@ -368,7 +412,6 @@ static void ensurePropertyMap()
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingRight, &RenderStyle::paddingRight, &RenderStyle::setPaddingRight));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingTop, &RenderStyle::paddingTop, &RenderStyle::setPaddingTop));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingBottom, &RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom));
- gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity));
gPropertyWrappers->append(new PropertyWrapper<const Color&>(CSSPropertyColor, &RenderStyle::color, &RenderStyle::setColor));
gPropertyWrappers->append(new PropertyWrapper<const Color&>(CSSPropertyBackgroundColor, &RenderStyle::backgroundColor, &RenderStyle::setBackgroundColor));
gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyFontSize, &RenderStyle::fontSize, &RenderStyle::setBlendedFontSize));
@@ -384,15 +427,27 @@ static void ensurePropertyMap()
gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth));
gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing));
gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing));
- gPropertyWrappers->append(new PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform));
+ gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitPerspective, &RenderStyle::perspective, &RenderStyle::setPerspective));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginX, &RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginY, &RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY));
+ gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitTransformOriginZ, &RenderStyle::transformOriginZ, &RenderStyle::setTransformOriginZ));
gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius));
gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius));
gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius));
gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius));
gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility));
gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoom));
+
+#if USE(ACCELERATED_COMPOSITING)
+ gPropertyWrappers->append(new PropertyWrapperAcceleratedOpacity());
+ gPropertyWrappers->append(new PropertyWrapperAcceleratedTransform());
+#else
+ gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity));
+ gPropertyWrappers->append(new PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform));
+#endif
+
gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyWebkitColumnRuleColor, &RenderStyle::columnRuleColor, &RenderStyle::setColumnRuleColor));
gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyWebkitTextStrokeColor, &RenderStyle::textStrokeColor, &RenderStyle::setTextStrokeColor));
gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyWebkitTextFillColor, &RenderStyle::textFillColor, &RenderStyle::setTextFillColor));
@@ -507,13 +562,13 @@ static PropertyWrapperBase* wrapperForProperty(int propertyID)
AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim)
: m_animState(AnimationStateNew)
, m_isAnimating(false)
- , m_waitedForResponse(false)
, m_startTime(0)
, m_pauseTime(-1)
, m_requestedStartTime(0)
, m_object(renderer)
, m_animation(const_cast<Animation*>(transition))
, m_compAnim(compAnim)
+ , m_fallbackAnimating(false)
, m_transformFunctionListValid(false)
, m_nextIterationDuration(-1)
, m_next(0)
@@ -526,8 +581,8 @@ AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer
AnimationBase::~AnimationBase()
{
- if (m_animState == AnimationStateStartWaitStyleAvailable)
- m_compAnim->removeFromStyleAvailableWaitList(this);
+ m_compAnim->removeFromStyleAvailableWaitList(this);
+ m_compAnim->removeFromStartTimeResponseWaitList(this);
}
bool AnimationBase::propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b)
@@ -575,12 +630,25 @@ bool AnimationBase::blendProperties(const AnimationBase* anim, int prop, RenderS
PropertyWrapperBase* wrapper = wrapperForProperty(prop);
if (wrapper) {
wrapper->blend(anim, dst, a, b, progress);
+#if USE(ACCELERATED_COMPOSITING)
+ return !wrapper->animationIsAccelerated() || anim->isFallbackAnimating();
+#else
return true;
+#endif
}
return false;
}
+#if USE(ACCELERATED_COMPOSITING)
+bool AnimationBase::animationOfPropertyIsAccelerated(int prop)
+{
+ ensurePropertyMap();
+ PropertyWrapperBase* wrapper = wrapperForProperty(prop);
+ return wrapper ? wrapper->animationIsAccelerated() : false;
+}
+#endif
+
void AnimationBase::setChanged(Node* node)
{
ASSERT(!node || (node->document() && !node->document()->inPageCache()));
@@ -614,7 +682,6 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
m_pauseTime = -1;
m_requestedStartTime = 0;
m_nextIterationDuration = -1;
- m_waitedForResponse = false;
endAnimation(false);
return;
}
@@ -661,11 +728,10 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
}
// Execute state machine
- switch(m_animState) {
+ switch (m_animState) {
case AnimationStateNew:
ASSERT(input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunnning || input == AnimationStateInputPlayStatePaused);
if (input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunnning) {
- m_waitedForResponse = false;
m_requestedStartTime = beginAnimationUpdateTime();
m_animState = AnimationStateStartWaitTimer;
}
@@ -681,7 +747,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
// Trigger a render so we can start the animation
if (m_object)
- m_object->animation()->addNodeChangeToDispatch(m_object->element());
+ m_compAnim->animationControllerPriv()->addNodeChangeToDispatch(m_object->node());
} else {
ASSERT(!paused());
// We're waiting for the start timer to fire and we got a pause. Cancel the timer, pause and wait
@@ -701,12 +767,18 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
onAnimationStart(0); // The elapsedTime is always 0 here
// Start the animation
- if (overridden() || !startAnimation(0)) {
- // We're not going to get a startTime callback, so fire the start time here
+ if (overridden()) {
+ // We won't try to start accelerated animations if we are overridden and
+ // just move on to the next state.
m_animState = AnimationStateStartWaitResponse;
+ m_fallbackAnimating = true;
updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime());
- } else
- m_waitedForResponse = true;
+ }
+ else {
+ bool started = startAnimation(0);
+ m_compAnim->addToStartTimeResponseWaitList(this, started);
+ m_fallbackAnimating = !started;
+ }
break;
case AnimationStateStartWaitResponse:
ASSERT(input == AnimationStateInputStartTimeSet || input == AnimationStateInputPlayStatePaused);
@@ -722,7 +794,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
// Dispatch updateRendering so we can start the animation
if (m_object)
- m_object->animation()->addNodeChangeToDispatch(m_object->element());
+ m_compAnim->animationControllerPriv()->addNodeChangeToDispatch(m_object->node());
} else {
// We are pausing while waiting for a start response. Cancel the animation and wait. When
// we unpause, we will act as though the start timer just fired
@@ -762,7 +834,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
resumeOverriddenAnimations();
// Fire off another style change so we can set the final value
- m_object->animation()->addNodeChangeToDispatch(m_object->element());
+ m_compAnim->animationControllerPriv()->addNodeChangeToDispatch(m_object->node());
}
} else {
// We are pausing while running. Cancel the animation and wait
@@ -789,8 +861,19 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
// AnimationStatePausedWaitResponse, we don't yet have a valid startTime, so we send 0 to startAnimation.
// When the AnimationStateInputStartTimeSet comes in and we were in AnimationStatePausedRun, we will notice
// that we have already set the startTime and will ignore it.
- ASSERT(input == AnimationStateInputPlayStateRunnning);
+ ASSERT(input == AnimationStateInputPlayStateRunnning || input == AnimationStateInputStartTimeSet);
ASSERT(paused());
+
+ // If we are paused, but we get the callback that notifies us that an accelerated animation started,
+ // then we ignore the start time and just move into the paused-run state.
+ if (m_animState == AnimationStatePausedWaitResponse && input == AnimationStateInputStartTimeSet) {
+ m_animState = AnimationStatePausedRun;
+ ASSERT(m_startTime == 0);
+ m_startTime = param;
+ m_pauseTime += m_startTime;
+ break;
+ }
+
// Update the times
if (m_animState == AnimationStatePausedRun)
m_startTime += beginAnimationUpdateTime() - m_pauseTime;
@@ -802,11 +885,16 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param)
m_animState = AnimationStateStartWaitResponse;
// Start the animation
- if (overridden() || !startAnimation(m_startTime)) {
- // We're not going to get a startTime callback, so fire the start time here
+ if (overridden()) {
+ // We won't try to start accelerated animations if we are overridden and
+ // just move on to the next state.
updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime());
- } else
- m_waitedForResponse = true;
+ m_fallbackAnimating = true;
+ } else {
+ bool started = startAnimation(0);
+ m_compAnim->addToStartTimeResponseWaitList(this, started);
+ m_fallbackAnimating = !started;
+ }
break;
case AnimationStateDone:
// We're done. Stay in this state until we are deleted
@@ -835,14 +923,16 @@ void AnimationBase::fireAnimationEventsIfNeeded()
}
double elapsedDuration = beginAnimationUpdateTime() - m_startTime;
- ASSERT(elapsedDuration >= 0);
+ // FIXME: we need to ensure that elapsedDuration is never < 0. If it is, this suggests that
+ // we had a recalcStyle() outside of beginAnimationUpdate()/endAnimationUpdate().
+ // Also check in getTimeToNextEvent().
+ elapsedDuration = max(elapsedDuration, 0.0);
// Check for end timeout
if (m_totalDuration >= 0 && elapsedDuration >= m_totalDuration) {
// Fire an end event
updateStateMachine(AnimationStateInputEndTimerFired, m_totalDuration);
- }
- else {
+ } else {
// Check for iteration timeout
if (m_nextIterationDuration < 0) {
// Hasn't been set yet, set it
@@ -868,18 +958,20 @@ void AnimationBase::updatePlayState(bool run)
updateStateMachine(run ? AnimationStateInputPlayStateRunnning : AnimationStateInputPlayStatePaused, -1);
}
-double AnimationBase::willNeedService() const
+double AnimationBase::willNeedService()
{
// Returns the time at which next service is required. -1 means no service is required. 0 means
// service is required now, and > 0 means service is required that many seconds in the future.
if (paused() || isNew())
return -1;
-
+
if (m_animState == AnimationStateStartWaitTimer) {
double timeFromNow = m_animation->delay() - (beginAnimationUpdateTime() - m_requestedStartTime);
- return (float) ((timeFromNow > 0) ? timeFromNow : 0);
+ return max(timeFromNow, 0.0);
}
+ fireAnimationEventsIfNeeded();
+
// In all other cases, we need service right away.
return 0;
}
@@ -926,31 +1018,40 @@ double AnimationBase::progress(double scale, double offset, const TimingFunction
return result;
}
-void AnimationBase::goIntoEndingOrLoopingState()
+void AnimationBase::getTimeToNextEvent(double& time, bool& isLooping) const
{
// Decide when the end or loop event needs to fire
double totalDuration = -1;
if (m_animation->iterationCount() > 0)
totalDuration = m_animation->duration() * m_animation->iterationCount();
- const double elapsedDuration = beginAnimationUpdateTime() - m_startTime;
- ASSERT(elapsedDuration >= 0);
+ const double elapsedDuration = max(beginAnimationUpdateTime() - m_startTime, 0.0);
double durationLeft = 0;
- double nextIterationTime = totalDuration;
+ double nextIterationTime = m_totalDuration;
- if (totalDuration < 0 || elapsedDuration < totalDuration) {
+ if (m_totalDuration < 0 || elapsedDuration < m_totalDuration) {
durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration());
nextIterationTime = elapsedDuration + durationLeft;
}
-
- if (totalDuration < 0 || nextIterationTime < totalDuration) {
+
+ if (m_totalDuration < 0 || nextIterationTime < m_totalDuration) {
// We are not at the end yet
ASSERT(nextIterationTime > 0);
- m_animState = AnimationStateLooping;
+ isLooping = true;
} else {
// We are at the end
- m_animState = AnimationStateEnding;
+ isLooping = false;
}
+
+ time = durationLeft;
+}
+
+void AnimationBase::goIntoEndingOrLoopingState()
+{
+ double t;
+ bool isLooping;
+ getTimeToNextEvent(t, isLooping);
+ m_animState = isLooping ? AnimationStateLooping : AnimationStateEnding;
}
void AnimationBase::pauseAtTime(double t)
@@ -961,7 +1062,7 @@ void AnimationBase::pauseAtTime(double t)
double AnimationBase::beginAnimationUpdateTime() const
{
- return m_compAnim->animationController()->beginAnimationUpdateTime();
+ return m_compAnim->animationControllerPriv()->beginAnimationUpdateTime();
}
double AnimationBase::getElapsedTime() const
diff --git a/WebCore/page/animation/AnimationBase.h b/WebCore/page/animation/AnimationBase.h
index ce16f93..da4341b 100644
--- a/WebCore/page/animation/AnimationBase.h
+++ b/WebCore/page/animation/AnimationBase.h
@@ -94,7 +94,10 @@ public:
void updateStateMachine(AnimStateInput, double param);
// Animation has actually started, at passed time
- void onAnimationStartResponse(double startTime);
+ void onAnimationStartResponse(double startTime)
+ {
+ updateStateMachine(AnimationBase::AnimationStateInputStartTimeSet, startTime);
+ }
// Called to change to or from paused state
void updatePlayState(bool running);
@@ -117,12 +120,12 @@ public:
// "animating" means that something is running that requires a timer to keep firing
// (e.g. a software animation)
void setAnimating(bool inAnimating = true) { m_isAnimating = inAnimating; }
- double willNeedService() const;
+ virtual double willNeedService();
double progress(double scale, double offset, const TimingFunction*) const;
- virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* /*currentStyle*/,
- const RenderStyle* /*targetStyle*/, RefPtr<RenderStyle>& /*animatedStyle*/) { }
+ virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* /*currentStyle*/, RenderStyle* /*targetStyle*/, RefPtr<RenderStyle>& /*animatedStyle*/) = 0;
+ virtual void getAnimatedStyle(RefPtr<RenderStyle>& /*animatedStyle*/) = 0;
virtual bool shouldFireEvents() const { return false; }
@@ -142,6 +145,9 @@ public:
virtual bool affectsProperty(int /*property*/) const { return false; }
bool isAnimatingProperty(int property, bool isRunningNow) const
{
+ if (m_fallbackAnimating)
+ return false;
+
if (isRunningNow)
return (!waitingToStart() && !postActive()) && affectsProperty(property);
@@ -164,7 +170,11 @@ public:
ASSERT(waitingForStyleAvailable());
updateStateMachine(AnimationBase::AnimationStateInputStyleAvailable, -1);
}
-
+
+#if USE(ACCELERATED_COMPOSITING)
+ static bool animationOfPropertyIsAccelerated(int prop);
+#endif
+
protected:
virtual void overrideAnimations() { }
virtual void resumeOverriddenAnimations() { }
@@ -176,23 +186,26 @@ protected:
virtual void onAnimationIteration(double /*elapsedTime*/) { }
virtual void onAnimationEnd(double /*elapsedTime*/) { }
virtual bool startAnimation(double /*beginTime*/) { return false; }
- virtual void endAnimation(bool /*reset*/) { }
+ virtual void endAnimation(bool /*reset*/, double /*forcePauseTime*/ = -1) { }
void goIntoEndingOrLoopingState();
+ bool isFallbackAnimating() const { return m_fallbackAnimating; }
+
static bool propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b);
static int getPropertyAtIndex(int, bool& isShorthand);
static int getNumProperties();
// Return true if we need to start software animation timers
static bool blendProperties(const AnimationBase* anim, int prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress);
-
+
static void setChanged(Node*);
+
+ void getTimeToNextEvent(double& time, bool& isLooping) const;
AnimState m_animState;
bool m_isAnimating; // transition/animation requires continual timer firing
- bool m_waitedForResponse;
double m_startTime;
double m_pauseTime;
double m_requestedStartTime;
@@ -200,6 +213,7 @@ protected:
RefPtr<Animation> m_animation;
CompositeAnimation* m_compAnim;
+ bool m_fallbackAnimating; // true when animating an accelerated property but have to fall back to software
bool m_transformFunctionListValid;
double m_totalDuration, m_nextIterationDuration;
diff --git a/WebCore/page/animation/AnimationController.cpp b/WebCore/page/animation/AnimationController.cpp
index f85e6c1..f9c9a47 100644
--- a/WebCore/page/animation/AnimationController.cpp
+++ b/WebCore/page/animation/AnimationController.cpp
@@ -28,84 +28,22 @@
#include "config.h"
#include "AnimationController.h"
+
#include "AnimationBase.h"
-#include "CompositeAnimation.h"
+#include "AnimationControllerPrivate.h"
#include "CSSParser.h"
+#include "CompositeAnimation.h"
#include "EventNames.h"
#include "Frame.h"
-#include "Timer.h"
+#include "RenderObject.h"
#include <wtf/CurrentTime.h>
+#include <wtf/UnusedParam.h>
namespace WebCore {
static const double cAnimationTimerDelay = 0.025;
static const double cBeginAnimationUpdateTimeNotSet = -1;
-class AnimationControllerPrivate {
-public:
- AnimationControllerPrivate(Frame*);
- ~AnimationControllerPrivate();
-
- PassRefPtr<CompositeAnimation> accessCompositeAnimation(RenderObject*);
- bool clear(RenderObject*);
-
- void animationTimerFired(Timer<AnimationControllerPrivate>*);
- void updateAnimationTimer(bool callSetChanged = false);
-
- void updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*);
- void startUpdateRenderingDispatcher();
- void addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime);
- void addNodeChangeToDispatch(PassRefPtr<Node>);
-
- bool hasAnimations() const { return !m_compositeAnimations.isEmpty(); }
-
- void suspendAnimations(Document*);
- void resumeAnimations(Document*);
-
- void styleAvailable();
-
- bool isAnimatingPropertyOnRenderer(RenderObject*, int property, bool isRunningNow) const;
-
- bool pauseAnimationAtTime(RenderObject*, const String& name, double t);
- bool pauseTransitionAtTime(RenderObject*, const String& property, double t);
- unsigned numberOfActiveAnimations() const;
-
- double beginAnimationUpdateTime()
- {
- if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet)
- m_beginAnimationUpdateTime = currentTime();
- return m_beginAnimationUpdateTime;
- }
-
- void setBeginAnimationUpdateTime(double t) { m_beginAnimationUpdateTime = t; }
-
- void addToStyleAvailableWaitList(AnimationBase*);
- void removeFromStyleAvailableWaitList(AnimationBase*);
-
-private:
- typedef HashMap<RenderObject*, RefPtr<CompositeAnimation> > RenderObjectAnimationMap;
-
- RenderObjectAnimationMap m_compositeAnimations;
- Timer<AnimationControllerPrivate> m_animationTimer;
- Timer<AnimationControllerPrivate> m_updateRenderingDispatcher;
- Frame* m_frame;
-
- class EventToDispatch {
- public:
- RefPtr<Element> element;
- AtomicString eventType;
- String name;
- double elapsedTime;
- };
-
- Vector<EventToDispatch> m_eventsToDispatch;
- Vector<RefPtr<Node> > m_nodeChangesToDispatch;
-
- double m_beginAnimationUpdateTime;
- AnimationBase* m_styleAvailableWaiters;
- AnimationBase* m_lastStyleAvailableWaiter;
-};
-
AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame)
: m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired)
, m_updateRenderingDispatcher(this, &AnimationControllerPrivate::updateRenderingDispatcherFired)
@@ -113,6 +51,9 @@ AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame)
, m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet)
, m_styleAvailableWaiters(0)
, m_lastStyleAvailableWaiter(0)
+ , m_responseWaiters(0)
+ , m_lastResponseWaiter(0)
+ , m_waitingForAResponse(false)
{
}
@@ -124,7 +65,7 @@ PassRefPtr<CompositeAnimation> AnimationControllerPrivate::accessCompositeAnimat
{
RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer);
if (!animation) {
- animation = CompositeAnimation::create(m_frame->animation());
+ animation = CompositeAnimation::create(this);
m_compositeAnimations.set(renderer, animation);
}
return animation;
@@ -155,7 +96,7 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa
needsService = t;
if (needsService == 0) {
if (callSetChanged) {
- Node* node = it->first->element();
+ Node* node = it->first->node();
ASSERT(!node || (node->document() && !node->document()->inPageCache()));
node->setChanged(AnimationStyleChange);
calledSetChanged = true;
@@ -209,7 +150,7 @@ void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationC
m_nodeChangesToDispatch.clear();
- if (m_frame && m_frame->document())
+ if (m_frame)
m_frame->document()->updateRendering();
}
@@ -233,6 +174,10 @@ void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element,
void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node)
{
+ ASSERT(!node || (node->document() && !node->document()->inPageCache()));
+ if (!node)
+ return;
+
m_nodeChangesToDispatch.append(node);
startUpdateRenderingDispatcher();
}
@@ -240,7 +185,7 @@ void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node)
void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>*)
{
// Make sure animationUpdateTime is updated, so that it is current even if no
- // styleChange has happened (e.g. hardware animations)
+ // styleChange has happened (e.g. accelerated animations)
setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
// When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate
@@ -248,7 +193,7 @@ void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPr
updateAnimationTimer(true);
}
-bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* renderer, int property, bool isRunningNow) const
+bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const
{
RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer);
if (!animation)
@@ -294,6 +239,7 @@ bool AnimationControllerPrivate::pauseAnimationAtTime(RenderObject* renderer, co
if (compAnim->pauseAnimationAtTime(name, t)) {
renderer->node()->setChanged(AnimationStyleChange);
+ startUpdateRenderingDispatcher();
return true;
}
@@ -311,12 +257,39 @@ bool AnimationControllerPrivate::pauseTransitionAtTime(RenderObject* renderer, c
if (compAnim->pauseTransitionAtTime(cssPropertyID(property), t)) {
renderer->node()->setChanged(AnimationStyleChange);
+ startUpdateRenderingDispatcher();
return true;
}
return false;
}
+double AnimationControllerPrivate::beginAnimationUpdateTime()
+{
+ if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet)
+ m_beginAnimationUpdateTime = currentTime();
+ return m_beginAnimationUpdateTime;
+}
+
+PassRefPtr<RenderStyle> AnimationControllerPrivate::getAnimatedStyleForRenderer(RenderObject* renderer)
+{
+ if (!renderer)
+ return 0;
+
+ RefPtr<CompositeAnimation> rendererAnimations = m_compositeAnimations.get(renderer);
+ if (!rendererAnimations)
+ return renderer->style();
+
+ // Make sure animationUpdateTime is updated, so that it is current even if no
+ // styleChange has happened (e.g. accelerated animations).
+ setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
+ RefPtr<RenderStyle> animatingStyle = rendererAnimations->getAnimatedStyle();
+ if (!animatingStyle)
+ animatingStyle = renderer->style();
+
+ return animatingStyle.release();
+}
+
unsigned AnimationControllerPrivate::numberOfActiveAnimations() const
{
unsigned count = 0;
@@ -364,13 +337,83 @@ void AnimationControllerPrivate::removeFromStyleAvailableWaitList(AnimationBase*
void AnimationControllerPrivate::styleAvailable()
{
// Go through list of waiters and send them on their way
- for (AnimationBase* animation = m_styleAvailableWaiters; animation; animation = animation->next())
+ for (AnimationBase* animation = m_styleAvailableWaiters; animation; ) {
+ AnimationBase* nextAnimation = animation->next();
+ animation->setNext(0);
animation->styleAvailable();
+ animation = nextAnimation;
+ }
m_styleAvailableWaiters = 0;
m_lastStyleAvailableWaiter = 0;
}
+void AnimationControllerPrivate::addToStartTimeResponseWaitList(AnimationBase* animation, bool willGetResponse)
+{
+ // If willGetResponse is true, it means this animation is actually waiting for a response
+ // (which will come in as a call to notifyAnimationStarted()).
+ // In that case we don't need to add it to this list. We just set a waitingForAResponse flag
+ // which says we are waiting for the response. If willGetResponse is false, this animation
+ // is not waiting for a response for itself, but rather for a notifyXXXStarted() call for
+ // another animation to which it will sync.
+ //
+ // When endAnimationUpdate() is called we check to see if the waitingForAResponse flag is
+ // true. If so, we just return and will do our work when the first notifyXXXStarted() call
+ // comes in. If it is false, we will not be getting a notifyXXXStarted() call, so we will
+ // do our work right away. In both cases we call the onAnimationStartResponse() method
+ // on each animation. In the first case we send in the time we got from notifyXXXStarted().
+ // In the second case, we just pass in the beginAnimationUpdateTime().
+ //
+ // This will synchronize all software and accelerated animations started in the same
+ // updateRendering cycle.
+ //
+ ASSERT(!animation->next());
+
+ if (willGetResponse)
+ m_waitingForAResponse = true;
+
+ if (m_responseWaiters)
+ m_lastResponseWaiter->setNext(animation);
+ else
+ m_responseWaiters = animation;
+
+ m_lastResponseWaiter = animation;
+ animation->setNext(0);
+}
+
+void AnimationControllerPrivate::removeFromStartTimeResponseWaitList(AnimationBase* animationToRemove)
+{
+ AnimationBase* prevAnimation = 0;
+ for (AnimationBase* animation = m_responseWaiters; animation; animation = animation->next()) {
+ if (animation == animationToRemove) {
+ if (prevAnimation)
+ prevAnimation->setNext(animation->next());
+ else
+ m_responseWaiters = animation->next();
+
+ if (m_lastResponseWaiter == animation)
+ m_lastResponseWaiter = prevAnimation;
+
+ animationToRemove->setNext(0);
+ }
+ prevAnimation = animation;
+ }
+}
+
+void AnimationControllerPrivate::startTimeResponse(double t)
+{
+ // Go through list of waiters and send them on their way
+ for (AnimationBase* animation = m_responseWaiters; animation; ) {
+ AnimationBase* nextAnimation = animation->next();
+ animation->setNext(0);
+ animation->onAnimationStartResponse(t);
+ animation = nextAnimation;
+ }
+
+ m_responseWaiters = 0;
+ m_lastResponseWaiter = 0;
+}
+
AnimationController::AnimationController(Frame* frame)
: m_data(new AnimationControllerPrivate(frame))
{
@@ -387,7 +430,7 @@ void AnimationController::cancelAnimations(RenderObject* renderer)
return;
if (m_data->clear(renderer)) {
- Node* node = renderer->element();
+ Node* node = renderer->node();
ASSERT(!node || (node->document() && !node->document()->inPageCache()));
node->setChanged(AnimationStyleChange);
}
@@ -408,7 +451,7 @@ PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject* rend
// against the animations in the style and make sure we're in sync. If destination values
// have changed, we reset the animation. We then do a blend to get new values and we return
// a new style.
- ASSERT(renderer->element()); // FIXME: We do not animate generated content yet.
+ ASSERT(renderer->node()); // FIXME: We do not animate generated content yet.
RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer);
RefPtr<RenderStyle> blendedStyle = rendererAnimations->animate(renderer, oldStyle, newStyle);
@@ -425,16 +468,14 @@ PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject* rend
return blendedStyle.release();
}
-void AnimationController::setAnimationStartTime(RenderObject* renderer, double t)
+PassRefPtr<RenderStyle> AnimationController::getAnimatedStyleForRenderer(RenderObject* renderer)
{
- RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer);
- rendererAnimations->setAnimationStartTime(t);
+ return m_data->getAnimatedStyleForRenderer(renderer);
}
-void AnimationController::setTransitionStartTime(RenderObject* renderer, int property, double t)
+void AnimationController::notifyAnimationStarted(RenderObject*, double startTime)
{
- RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer);
- rendererAnimations->setTransitionStartTime(property, t);
+ m_data->receivedStartTimeResponse(startTime);
}
bool AnimationController::pauseAnimationAtTime(RenderObject* renderer, const String& name, double t)
@@ -452,7 +493,7 @@ bool AnimationController::pauseTransitionAtTime(RenderObject* renderer, const St
return m_data->pauseTransitionAtTime(renderer, property, t);
}
-bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* renderer, int property, bool isRunningNow) const
+bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const
{
return m_data->isAnimatingPropertyOnRenderer(renderer, property, isRunningNow);
}
@@ -467,28 +508,6 @@ void AnimationController::resumeAnimations(Document* document)
m_data->resumeAnimations(document);
}
-void AnimationController::startUpdateRenderingDispatcher()
-{
- m_data->startUpdateRenderingDispatcher();
-}
-
-void AnimationController::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime)
-{
- m_data->addEventToDispatch(element, eventType, name, elapsedTime);
-}
-
-void AnimationController::addNodeChangeToDispatch(PassRefPtr<Node> node)
-{
- ASSERT(!node || (node->document() && !node->document()->inPageCache()));
- if (node)
- m_data->addNodeChangeToDispatch(node);
-}
-
-double AnimationController::beginAnimationUpdateTime()
-{
- return m_data->beginAnimationUpdateTime();
-}
-
void AnimationController::beginAnimationUpdate()
{
m_data->setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
@@ -496,17 +515,17 @@ void AnimationController::beginAnimationUpdate()
void AnimationController::endAnimationUpdate()
{
- m_data->styleAvailable();
+ m_data->endAnimationUpdate();
}
-void AnimationController::addToStyleAvailableWaitList(AnimationBase* animation)
+bool AnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property)
{
- m_data->addToStyleAvailableWaitList(animation);
-}
-
-void AnimationController::removeFromStyleAvailableWaitList(AnimationBase* animation)
-{
- m_data->removeFromStyleAvailableWaitList(animation);
+#if USE(ACCELERATED_COMPOSITING)
+ return AnimationBase::animationOfPropertyIsAccelerated(property);
+#else
+ UNUSED_PARAM(property);
+ return false;
+#endif
}
} // namespace WebCore
diff --git a/WebCore/page/animation/AnimationController.h b/WebCore/page/animation/AnimationController.h
index 13ea1bd..db82618 100644
--- a/WebCore/page/animation/AnimationController.h
+++ b/WebCore/page/animation/AnimationController.h
@@ -29,6 +29,7 @@
#ifndef AnimationController_h
#define AnimationController_h
+#include "CSSPropertyNames.h"
#include <wtf/Forward.h>
namespace WebCore {
@@ -51,30 +52,24 @@ public:
void cancelAnimations(RenderObject*);
PassRefPtr<RenderStyle> updateAnimations(RenderObject*, RenderStyle* newStyle);
+ PassRefPtr<RenderStyle> getAnimatedStyleForRenderer(RenderObject*);
- void setAnimationStartTime(RenderObject*, double t);
- void setTransitionStartTime(RenderObject*, int property, double t);
+ // This is called when an accelerated animation or transition has actually started to animate.
+ void notifyAnimationStarted(RenderObject*, double startTime);
bool pauseAnimationAtTime(RenderObject*, const String& name, double t); // To be used only for testing
bool pauseTransitionAtTime(RenderObject*, const String& property, double t); // To be used only for testing
unsigned numberOfActiveAnimations() const; // To be used only for testing
- bool isAnimatingPropertyOnRenderer(RenderObject*, int property, bool isRunningNow) const;
+ bool isAnimatingPropertyOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow = true) const;
void suspendAnimations(Document*);
void resumeAnimations(Document*);
- void startUpdateRenderingDispatcher();
- void addEventToDispatch(PassRefPtr<Element>, const AtomicString& eventType, const String& name, double elapsedTime);
- void addNodeChangeToDispatch(PassRefPtr<Node>);
-
- void addToStyleAvailableWaitList(AnimationBase*);
- void removeFromStyleAvailableWaitList(AnimationBase*);
-
- double beginAnimationUpdateTime();
-
void beginAnimationUpdate();
void endAnimationUpdate();
+
+ static bool supportsAcceleratedAnimationOfProperty(CSSPropertyID);
private:
AnimationControllerPrivate* m_data;
diff --git a/WebCore/page/animation/AnimationControllerPrivate.h b/WebCore/page/animation/AnimationControllerPrivate.h
new file mode 100644
index 0000000..f9a3405
--- /dev/null
+++ b/WebCore/page/animation/AnimationControllerPrivate.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef AnimationControllerPrivate_h
+#define AnimationControllerPrivate_h
+
+#include "AtomicString.h"
+#include "CSSPropertyNames.h"
+#include "PlatformString.h"
+#include "Timer.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class AnimationBase;
+class CompositeAnimation;
+class Document;
+class Element;
+class Frame;
+class Node;
+class RenderObject;
+class RenderStyle;
+
+class AnimationControllerPrivate {
+public:
+ AnimationControllerPrivate(Frame*);
+ ~AnimationControllerPrivate();
+
+ PassRefPtr<CompositeAnimation> accessCompositeAnimation(RenderObject*);
+ bool clear(RenderObject*);
+
+ void animationTimerFired(Timer<AnimationControllerPrivate>*);
+ void updateAnimationTimer(bool callSetChanged = false);
+
+ void updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*);
+ void startUpdateRenderingDispatcher();
+ void addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime);
+ void addNodeChangeToDispatch(PassRefPtr<Node>);
+
+ bool hasAnimations() const { return !m_compositeAnimations.isEmpty(); }
+
+ void suspendAnimations(Document*);
+ void resumeAnimations(Document*);
+
+ bool isAnimatingPropertyOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow) const;
+
+ bool pauseAnimationAtTime(RenderObject*, const String& name, double t);
+ bool pauseTransitionAtTime(RenderObject*, const String& property, double t);
+ unsigned numberOfActiveAnimations() const;
+
+ PassRefPtr<RenderStyle> getAnimatedStyleForRenderer(RenderObject* renderer);
+
+ double beginAnimationUpdateTime();
+ void setBeginAnimationUpdateTime(double t) { m_beginAnimationUpdateTime = t; }
+ void endAnimationUpdate()
+ {
+ styleAvailable();
+ if (!m_waitingForAResponse)
+ startTimeResponse(beginAnimationUpdateTime());
+ }
+
+ void receivedStartTimeResponse(double t)
+ {
+ m_waitingForAResponse = false;
+ startTimeResponse(t);
+ }
+
+ void addToStyleAvailableWaitList(AnimationBase*);
+ void removeFromStyleAvailableWaitList(AnimationBase*);
+
+ void addToStartTimeResponseWaitList(AnimationBase*, bool willGetResponse);
+ void removeFromStartTimeResponseWaitList(AnimationBase*);
+ void startTimeResponse(double t);
+
+private:
+ void styleAvailable();
+
+ typedef HashMap<RenderObject*, RefPtr<CompositeAnimation> > RenderObjectAnimationMap;
+
+ RenderObjectAnimationMap m_compositeAnimations;
+ Timer<AnimationControllerPrivate> m_animationTimer;
+ Timer<AnimationControllerPrivate> m_updateRenderingDispatcher;
+ Frame* m_frame;
+
+ class EventToDispatch {
+ public:
+ RefPtr<Element> element;
+ AtomicString eventType;
+ String name;
+ double elapsedTime;
+ };
+
+ Vector<EventToDispatch> m_eventsToDispatch;
+ Vector<RefPtr<Node> > m_nodeChangesToDispatch;
+
+ double m_beginAnimationUpdateTime;
+ AnimationBase* m_styleAvailableWaiters;
+ AnimationBase* m_lastStyleAvailableWaiter;
+
+ AnimationBase* m_responseWaiters;
+ AnimationBase* m_lastResponseWaiter;
+ bool m_waitingForAResponse;
+};
+
+} // namespace WebCore
+
+#endif // AnimationControllerPrivate_h
diff --git a/WebCore/page/animation/CompositeAnimation.cpp b/WebCore/page/animation/CompositeAnimation.cpp
index bf61b78..d386f1b 100644
--- a/WebCore/page/animation/CompositeAnimation.cpp
+++ b/WebCore/page/animation/CompositeAnimation.cpp
@@ -29,7 +29,7 @@
#include "config.h"
#include "CompositeAnimation.h"
-#include "AnimationController.h"
+#include "AnimationControllerPrivate.h"
#include "CSSPropertyNames.h"
#include "ImplicitAnimation.h"
#include "KeyframeAnimation.h"
@@ -40,7 +40,7 @@ namespace WebCore {
class CompositeAnimationPrivate {
public:
- CompositeAnimationPrivate(AnimationController* animationController, CompositeAnimation* compositeAnimation)
+ CompositeAnimationPrivate(AnimationControllerPrivate* animationController, CompositeAnimation* compositeAnimation)
: m_isSuspended(false)
, m_animationController(animationController)
, m_compositeAnimation(compositeAnimation)
@@ -53,8 +53,9 @@ public:
void clearRenderer();
PassRefPtr<RenderStyle> animate(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle);
+ PassRefPtr<RenderStyle> getAnimatedStyle();
- AnimationController* animationController() { return m_animationController; }
+ AnimationControllerPrivate* animationControllerPriv() const { return m_animationController; }
void setAnimating(bool);
double willNeedService() const;
@@ -63,9 +64,6 @@ public:
void cleanupFinishedAnimations(RenderObject*);
- void setAnimationStartTime(double t);
- void setTransitionStartTime(int property, double t);
-
void suspendAnimations();
void resumeAnimations();
bool isSuspended() const { return m_isSuspended; }
@@ -80,6 +78,9 @@ public:
void addToStyleAvailableWaitList(AnimationBase*);
void removeFromStyleAvailableWaitList(AnimationBase*);
+ void addToStartTimeResponseWaitList(AnimationBase*, bool willGetResponse);
+ void removeFromStartTimeResponseWaitList(AnimationBase*);
+
bool pauseAnimationAtTime(const AtomicString& name, double t);
bool pauseTransitionAtTime(int property, double t);
unsigned numberOfActiveAnimations() const;
@@ -94,8 +95,9 @@ private:
CSSPropertyTransitionsMap m_transitions;
AnimationNameMap m_keyframeAnimations;
+ Vector<AtomicStringImpl*> m_keyframeAnimationOrderMap;
bool m_isSuspended;
- AnimationController* m_animationController;
+ AnimationControllerPrivate* m_animationController;
CompositeAnimation* m_compositeAnimation;
unsigned m_numStyleAvailableWaiters;
};
@@ -126,9 +128,11 @@ void CompositeAnimationPrivate::clearRenderer()
}
}
}
-
+
void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle)
{
+ RefPtr<RenderStyle> modifiedCurrentStyle;
+
// If currentStyle is null, we don't do transitions
if (!currentStyle || !targetStyle->transitions())
return;
@@ -176,6 +180,16 @@ void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, Render
// list. In this case, the latter one overrides the earlier one, so we
// behave as though this is a running animation being replaced.
if (!implAnim->isTargetPropertyEqual(prop, targetStyle)) {
+#if USE(ACCELERATED_COMPOSITING)
+ // For accelerated animations we need to return a new RenderStyle with the _current_ value
+ // of the property, so that restarted transitions use the correct starting point.
+ if (AnimationBase::animationOfPropertyIsAccelerated(prop) && !implAnim->isFallbackAnimating()) {
+ if (!modifiedCurrentStyle)
+ modifiedCurrentStyle = RenderStyle::clone(currentStyle);
+
+ implAnim->blendPropertyValueInStyle(prop, modifiedCurrentStyle.get());
+ }
+#endif
m_transitions.remove(prop);
equal = false;
}
@@ -186,7 +200,7 @@ void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, Render
if (!equal) {
// Add the new transition
- m_transitions.set(prop, ImplicitAnimation::create(const_cast<Animation*>(anim), prop, renderer, m_compositeAnimation, fromStyle));
+ m_transitions.set(prop, ImplicitAnimation::create(const_cast<Animation*>(anim), prop, renderer, m_compositeAnimation, modifiedCurrentStyle ? modifiedCurrentStyle.get() : fromStyle));
}
// We only need one pass for the single prop case
@@ -210,6 +224,9 @@ void CompositeAnimationPrivate::updateKeyframeAnimations(RenderObject* renderer,
AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end();
for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it)
it->second->setIndex(-1);
+
+ // Toss the animation order map
+ m_keyframeAnimationOrderMap.clear();
// Now mark any still active animations as active and add any new animations
if (targetStyle->animations()) {
@@ -237,6 +254,10 @@ void CompositeAnimationPrivate::updateKeyframeAnimations(RenderObject* renderer,
keyframeAnim = KeyframeAnimation::create(const_cast<Animation*>(anim), renderer, i, m_compositeAnimation, currentStyle ? currentStyle : targetStyle);
m_keyframeAnimations.set(keyframeAnim->name().impl(), keyframeAnim);
}
+
+ // Add this to the animation order map
+ if (keyframeAnim)
+ m_keyframeAnimationOrderMap.append(keyframeAnim->name().impl());
}
}
@@ -278,17 +299,10 @@ PassRefPtr<RenderStyle> CompositeAnimationPrivate::animate(RenderObject* rendere
// Now that we have animation objects ready, let them know about the new goal state. We want them
// to fill in a RenderStyle*& only if needed.
- if (targetStyle->hasAnimations()) {
- for (size_t i = 0; i < targetStyle->animations()->size(); ++i) {
- const Animation* anim = targetStyle->animations()->animation(i);
-
- if (anim->isValidAnimation()) {
- AtomicString animationName(anim->name());
- RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(animationName.impl());
- if (keyframeAnim)
- keyframeAnim->animate(m_compositeAnimation, renderer, currentStyle, targetStyle, resultStyle);
- }
- }
+ for (Vector<AtomicStringImpl*>::const_iterator it = m_keyframeAnimationOrderMap.begin(); it != m_keyframeAnimationOrderMap.end(); ++it) {
+ RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(*it);
+ if (keyframeAnim)
+ keyframeAnim->animate(m_compositeAnimation, renderer, currentStyle, targetStyle, resultStyle);
}
cleanupFinishedAnimations(renderer);
@@ -296,6 +310,24 @@ PassRefPtr<RenderStyle> CompositeAnimationPrivate::animate(RenderObject* rendere
return resultStyle ? resultStyle.release() : targetStyle;
}
+PassRefPtr<RenderStyle> CompositeAnimationPrivate::getAnimatedStyle()
+{
+ RefPtr<RenderStyle> resultStyle;
+ CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
+ for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
+ if (ImplicitAnimation* implicitAnimation = it->second.get())
+ implicitAnimation->getAnimatedStyle(resultStyle);
+ }
+
+ for (Vector<AtomicStringImpl*>::const_iterator it = m_keyframeAnimationOrderMap.begin(); it != m_keyframeAnimationOrderMap.end(); ++it) {
+ RefPtr<KeyframeAnimation> keyframeAnimation = m_keyframeAnimations.get(*it);
+ if (keyframeAnimation)
+ keyframeAnimation->getAnimatedStyle(resultStyle);
+ }
+
+ return resultStyle;
+}
+
// "animating" means that something is running that requires the timer to keep firing
void CompositeAnimationPrivate::setAnimating(bool animating)
{
@@ -409,32 +441,6 @@ void CompositeAnimationPrivate::cleanupFinishedAnimations(RenderObject*)
}
}
-void CompositeAnimationPrivate::setAnimationStartTime(double t)
-{
- // Set start time on all animations waiting for it
- if (!m_keyframeAnimations.isEmpty()) {
- AnimationNameMap::const_iterator end = m_keyframeAnimations.end();
- for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != end; ++it) {
- KeyframeAnimation* anim = it->second.get();
- if (anim && anim->waitingForStartTime())
- anim->updateStateMachine(AnimationBase::AnimationStateInputStartTimeSet, t);
- }
- }
-}
-
-void CompositeAnimationPrivate::setTransitionStartTime(int property, double t)
-{
- // Set the start time for given property transition
- if (!m_transitions.isEmpty()) {
- CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
- for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
- ImplicitAnimation* anim = it->second.get();
- if (anim && anim->waitingForStartTime() && anim->animatingProperty() == property)
- anim->updateStateMachine(AnimationBase::AnimationStateInputStartTimeSet, t);
- }
- }
-}
-
void CompositeAnimationPrivate::suspendAnimations()
{
if (m_isSuspended)
@@ -541,6 +547,16 @@ void CompositeAnimationPrivate::removeFromStyleAvailableWaitList(AnimationBase*
m_animationController->removeFromStyleAvailableWaitList(animation);
}
+void CompositeAnimationPrivate::addToStartTimeResponseWaitList(AnimationBase* animation, bool willGetResponse)
+{
+ m_animationController->addToStartTimeResponseWaitList(animation, willGetResponse);
+}
+
+void CompositeAnimationPrivate::removeFromStartTimeResponseWaitList(AnimationBase* animation)
+{
+ m_animationController->removeFromStartTimeResponseWaitList(animation);
+}
+
bool CompositeAnimationPrivate::pauseAnimationAtTime(const AtomicString& name, double t)
{
if (!name)
@@ -601,7 +617,7 @@ unsigned CompositeAnimationPrivate::numberOfActiveAnimations() const
return count;
}
-CompositeAnimation::CompositeAnimation(AnimationController* animationController)
+CompositeAnimation::CompositeAnimation(AnimationControllerPrivate* animationController)
: m_data(new CompositeAnimationPrivate(animationController, this))
{
}
@@ -611,9 +627,9 @@ CompositeAnimation::~CompositeAnimation()
delete m_data;
}
-AnimationController* CompositeAnimation::animationController()
+AnimationControllerPrivate* CompositeAnimation::animationControllerPriv() const
{
- return m_data->animationController();
+ return m_data->animationControllerPriv();
}
void CompositeAnimation::clearRenderer()
@@ -626,6 +642,11 @@ PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject* renderer, Rend
return m_data->animate(renderer, currentStyle, targetStyle);
}
+PassRefPtr<RenderStyle> CompositeAnimation::getAnimatedStyle()
+{
+ return m_data->getAnimatedStyle();
+}
+
double CompositeAnimation::willNeedService() const
{
return m_data->willNeedService();
@@ -641,6 +662,16 @@ void CompositeAnimation::removeFromStyleAvailableWaitList(AnimationBase* animati
m_data->removeFromStyleAvailableWaitList(animation);
}
+void CompositeAnimation::addToStartTimeResponseWaitList(AnimationBase* animation, bool willGetResponse)
+{
+ m_data->addToStartTimeResponseWaitList(animation, willGetResponse);
+}
+
+void CompositeAnimation::removeFromStartTimeResponseWaitList(AnimationBase* animation)
+{
+ m_data->removeFromStartTimeResponseWaitList(animation);
+}
+
void CompositeAnimation::suspendAnimations()
{
m_data->suspendAnimations();
@@ -676,16 +707,6 @@ PassRefPtr<KeyframeAnimation> CompositeAnimation::getAnimationForProperty(int pr
return m_data->getAnimationForProperty(property);
}
-void CompositeAnimation::setAnimationStartTime(double t)
-{
- m_data->setAnimationStartTime(t);
-}
-
-void CompositeAnimation::setTransitionStartTime(int property, double t)
-{
- m_data->setTransitionStartTime(property, t);
-}
-
void CompositeAnimation::overrideImplicitAnimations(int property)
{
m_data->overrideImplicitAnimations(property);
diff --git a/WebCore/page/animation/CompositeAnimation.h b/WebCore/page/animation/CompositeAnimation.h
index 3517b34..b5857aa 100644
--- a/WebCore/page/animation/CompositeAnimation.h
+++ b/WebCore/page/animation/CompositeAnimation.h
@@ -36,6 +36,7 @@
namespace WebCore {
+class AnimationControllerPrivate;
class CompositeAnimationPrivate;
class AnimationBase;
class AnimationController;
@@ -47,7 +48,7 @@ class RenderStyle;
// on a single RenderObject, such as a number of properties transitioning at once.
class CompositeAnimation : public RefCounted<CompositeAnimation> {
public:
- static PassRefPtr<CompositeAnimation> create(AnimationController* animationController)
+ static PassRefPtr<CompositeAnimation> create(AnimationControllerPrivate* animationController)
{
return adoptRef(new CompositeAnimation(animationController));
};
@@ -57,9 +58,17 @@ public:
void clearRenderer();
PassRefPtr<RenderStyle> animate(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle);
+ PassRefPtr<RenderStyle> getAnimatedStyle();
+
double willNeedService() const;
- AnimationController* animationController();
+ AnimationControllerPrivate* animationControllerPriv() const;
+
+ void addToStyleAvailableWaitList(AnimationBase*);
+ void removeFromStyleAvailableWaitList(AnimationBase*);
+
+ void addToStartTimeResponseWaitList(AnimationBase*, bool willGetResponse);
+ void removeFromStartTimeResponseWaitList(AnimationBase*);
void suspendAnimations();
void resumeAnimations();
@@ -72,10 +81,6 @@ public:
PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property);
-
- void setAnimationStartTime(double t);
- void setTransitionStartTime(int property, double t);
-
void overrideImplicitAnimations(int property);
void resumeOverriddenImplicitAnimations(int property);
@@ -83,11 +88,8 @@ public:
bool pauseTransitionAtTime(int property, double t);
unsigned numberOfActiveAnimations() const;
- void addToStyleAvailableWaitList(AnimationBase*);
- void removeFromStyleAvailableWaitList(AnimationBase*);
-
private:
- CompositeAnimation(AnimationController* animationController);
+ CompositeAnimation(AnimationControllerPrivate* animationController);
CompositeAnimationPrivate* m_data;
};
diff --git a/WebCore/page/animation/ImplicitAnimation.cpp b/WebCore/page/animation/ImplicitAnimation.cpp
index f984909..8ec0be0 100644
--- a/WebCore/page/animation/ImplicitAnimation.cpp
+++ b/WebCore/page/animation/ImplicitAnimation.cpp
@@ -28,13 +28,15 @@
#include "config.h"
-#include "AnimationController.h"
+#include "AnimationControllerPrivate.h"
#include "CompositeAnimation.h"
#include "CSSPropertyNames.h"
#include "EventNames.h"
#include "ImplicitAnimation.h"
#include "KeyframeAnimation.h"
-#include "RenderObject.h"
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
+#include <wtf/UnusedParam.h>
namespace WebCore {
@@ -55,12 +57,12 @@ ImplicitAnimation::~ImplicitAnimation()
updateStateMachine(AnimationStateInputEndAnimation, -1);
}
-bool ImplicitAnimation::shouldSendEventForListener(Document::ListenerType inListenerType)
+bool ImplicitAnimation::shouldSendEventForListener(Document::ListenerType inListenerType) const
{
return m_object->document()->hasListenerType(inListenerType);
}
-void ImplicitAnimation::animate(CompositeAnimation*, RenderObject*, RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
+void ImplicitAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
{
// If we get this far and the animation is done, it means we are cleaning up a just finished animation.
// So just return. Everything is already all cleaned up.
@@ -76,13 +78,58 @@ void ImplicitAnimation::animate(CompositeAnimation*, RenderObject*, RenderStyle*
if (!animatedStyle)
animatedStyle = RenderStyle::clone(targetStyle);
- if (blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0)))
+ bool needsAnim = blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0));
+ // FIXME: we also need to detect cases where we have to software animate for other reasons,
+ // such as a child using inheriting the transform. https://bugs.webkit.org/show_bug.cgi?id=23902
+ if (needsAnim)
setAnimating();
+ else {
+#if USE(ACCELERATED_COMPOSITING)
+ // If we are running an accelerated animation, set a flag in the style which causes the style
+ // to compare as different to any other style. This ensures that changes to the property
+ // that is animating are correctly detected during the animation (e.g. when a transition
+ // gets interrupted).
+ animatedStyle->setIsRunningAcceleratedAnimation();
+#endif
+ }
// Fire the start timeout if needed
fireAnimationEventsIfNeeded();
}
+void ImplicitAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle)
+{
+ if (!animatedStyle)
+ animatedStyle = RenderStyle::clone(m_toStyle.get());
+
+ blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0));
+}
+
+bool ImplicitAnimation::startAnimation(double beginTime)
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_object && m_object->hasLayer()) {
+ RenderLayer* layer = toRenderBoxModelObject(m_object)->layer();
+ if (layer->isComposited())
+ return layer->backing()->startTransition(beginTime, m_animatingProperty, m_fromStyle.get(), m_toStyle.get());
+ }
+#else
+ UNUSED_PARAM(beginTime);
+#endif
+ return false;
+}
+
+void ImplicitAnimation::endAnimation(bool /*reset*/)
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_object && m_object->hasLayer()) {
+ RenderLayer* layer = toRenderBoxModelObject(m_object)->layer();
+ if (layer->isComposited())
+ layer->backing()->transitionFinished(m_animatingProperty);
+ }
+#endif
+}
+
void ImplicitAnimation::onAnimationEnd(double elapsedTime)
{
// If we have a keyframe animation on this property, this transition is being overridden. The keyframe
@@ -120,7 +167,7 @@ bool ImplicitAnimation::sendTransitionEvent(const AtomicString& eventType, doubl
return false;
// Schedule event handling
- m_object->animation()->addEventToDispatch(element, eventType, propertyName, elapsedTime);
+ m_compAnim->animationControllerPriv()->addEventToDispatch(element, eventType, propertyName, elapsedTime);
// Restore the original (unanimated) style
if (eventType == eventNames().webkitTransitionEndEvent && element->renderer())
@@ -137,7 +184,6 @@ void ImplicitAnimation::reset(RenderStyle* to)
{
ASSERT(to);
ASSERT(m_fromStyle);
-
m_toStyle = to;
@@ -209,4 +255,21 @@ void ImplicitAnimation::validateTransformFunctionList()
m_transformFunctionListValid = true;
}
+double ImplicitAnimation::willNeedService()
+{
+ double t = AnimationBase::willNeedService();
+#if USE(ACCELERATED_COMPOSITING)
+ if (t != 0 || preActive())
+ return t;
+
+ // A return value of 0 means we need service. But if this is an accelerated animation we
+ // only need service at the end of the transition.
+ if (animationOfPropertyIsAccelerated(m_animatingProperty) && !isFallbackAnimating()) {
+ bool isLooping;
+ getTimeToNextEvent(t, isLooping);
+ }
+#endif
+ return t;
+}
+
} // namespace WebCore
diff --git a/WebCore/page/animation/ImplicitAnimation.h b/WebCore/page/animation/ImplicitAnimation.h
index cf98bba..221c45e 100644
--- a/WebCore/page/animation/ImplicitAnimation.h
+++ b/WebCore/page/animation/ImplicitAnimation.h
@@ -47,8 +47,11 @@ public:
int animatingProperty() const { return m_animatingProperty; }
virtual void onAnimationEnd(double elapsedTime);
+ virtual bool startAnimation(double beginTime);
+ virtual void endAnimation(bool reset);
- virtual void animate(CompositeAnimation*, RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle);
+ virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle);
+ virtual void getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle);
virtual void reset(RenderStyle* to);
void setOverridden(bool);
@@ -62,8 +65,10 @@ public:
void blendPropertyValueInStyle(int, RenderStyle* currentStyle);
+ virtual double willNeedService();
+
protected:
- bool shouldSendEventForListener(Document::ListenerType);
+ bool shouldSendEventForListener(Document::ListenerType) const;
bool sendTransitionEvent(const AtomicString&, double elapsedTime);
void validateTransformFunctionList();
diff --git a/WebCore/page/animation/KeyframeAnimation.cpp b/WebCore/page/animation/KeyframeAnimation.cpp
index 2efa578..88a5f6a 100644
--- a/WebCore/page/animation/KeyframeAnimation.cpp
+++ b/WebCore/page/animation/KeyframeAnimation.cpp
@@ -29,12 +29,14 @@
#include "config.h"
#include "KeyframeAnimation.h"
-#include "AnimationController.h"
+#include "AnimationControllerPrivate.h"
#include "CSSPropertyNames.h"
#include "CSSStyleSelector.h"
#include "CompositeAnimation.h"
#include "EventNames.h"
-#include "RenderObject.h"
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
+#include <wtf/UnusedParam.h>
namespace WebCore {
@@ -45,8 +47,8 @@ KeyframeAnimation::KeyframeAnimation(const Animation* animation, RenderObject* r
, m_unanimatedStyle(unanimatedStyle)
{
// Get the keyframe RenderStyles
- if (m_object && m_object->element() && m_object->element()->isElementNode())
- m_object->document()->styleSelector()->keyframeStylesForAnimation(static_cast<Element*>(m_object->element()), unanimatedStyle, m_keyframes);
+ if (m_object && m_object->node() && m_object->node()->isElementNode())
+ m_object->document()->styleSelector()->keyframeStylesForAnimation(static_cast<Element*>(m_object->node()), unanimatedStyle, m_keyframes);
// Update the m_transformFunctionListValid flag based on whether the function lists in the keyframes match.
validateTransformFunctionList();
@@ -59,32 +61,8 @@ KeyframeAnimation::~KeyframeAnimation()
updateStateMachine(AnimationStateInputEndAnimation, -1);
}
-void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, const RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
+void KeyframeAnimation::getKeyframeAnimationInterval(const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& prog) const
{
- // Fire the start timeout if needed
- fireAnimationEventsIfNeeded();
-
- // If we have not yet started, we will not have a valid start time, so just start the animation if needed.
- if (isNew() && m_animation->playState() == AnimPlayStatePlaying)
- updateStateMachine(AnimationStateInputStartAnimation, -1);
-
- // If we get this far and the animation is done, it means we are cleaning up a just finished animation.
- // If so, we need to send back the targetStyle.
- if (postActive()) {
- if (!animatedStyle)
- animatedStyle = const_cast<RenderStyle*>(targetStyle);
- return;
- }
-
- // If we are waiting for the start timer, we don't want to change the style yet.
- // Special case - if the delay time is 0, then we do want to set the first frame of the
- // animation right away. This avoids a flash when the animation starts.
- if (waitingToStart() && m_animation->delay() > 0)
- return;
-
- // FIXME: we need to be more efficient about determining which keyframes we are animating between.
- // We should cache the last pair or something.
-
// Find the first key
double elapsedTime = getElapsedTime();
@@ -94,8 +72,6 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render
if (m_animation->direction() && (i & 1))
t = 1 - t;
- const RenderStyle* fromStyle = 0;
- const RenderStyle* toStyle = 0;
double scale = 1;
double offset = 0;
Vector<KeyframeValue>::const_iterator endKeyframes = m_keyframes.endKeyframes();
@@ -113,6 +89,48 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render
fromStyle = it->style();
}
+ if (!fromStyle || !toStyle)
+ return;
+
+ const TimingFunction* timingFunction = 0;
+ if (fromStyle->animations() && fromStyle->animations()->size() > 0)
+ timingFunction = &(fromStyle->animations()->animation(0)->timingFunction());
+
+ prog = progress(scale, offset, timingFunction);
+}
+
+void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
+{
+ // Fire the start timeout if needed
+ fireAnimationEventsIfNeeded();
+
+ // If we have not yet started, we will not have a valid start time, so just start the animation if needed.
+ if (isNew() && m_animation->playState() == AnimPlayStatePlaying)
+ updateStateMachine(AnimationStateInputStartAnimation, -1);
+
+ // If we get this far and the animation is done, it means we are cleaning up a just finished animation.
+ // If so, we need to send back the targetStyle.
+ if (postActive()) {
+ if (!animatedStyle)
+ animatedStyle = const_cast<RenderStyle*>(targetStyle);
+ return;
+ }
+
+ // If we are waiting for the start timer, we don't want to change the style yet.
+ // Special case - if the delay time is 0, then we do want to set the first frame of the
+ // animation right away. This avoids a flash when the animation starts.
+ if (waitingToStart() && m_animation->delay() > 0)
+ return;
+
+ // FIXME: we need to be more efficient about determining which keyframes we are animating between.
+ // We should cache the last pair or something.
+
+ // Get the from/to styles and progress between
+ const RenderStyle* fromStyle = 0;
+ const RenderStyle* toStyle = 0;
+ double progress;
+ getKeyframeAnimationInterval(fromStyle, toStyle, progress);
+
// If either style is 0 we have an invalid case, just stop the animation.
if (!fromStyle || !toStyle) {
updateStateMachine(AnimationStateInputEndAnimation, -1);
@@ -124,19 +142,42 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render
if (!animatedStyle)
animatedStyle = RenderStyle::clone(targetStyle);
- const TimingFunction* timingFunction = 0;
- if (fromStyle->animations() && fromStyle->animations()->size() > 0)
- timingFunction = &(fromStyle->animations()->animation(0)->timingFunction());
-
- double prog = progress(scale, offset, timingFunction);
-
HashSet<int>::const_iterator endProperties = m_keyframes.endProperties();
for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) {
- if (blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, prog))
+ bool needsAnim = blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress);
+ if (needsAnim)
setAnimating();
+ else {
+#if USE(ACCELERATED_COMPOSITING)
+ // If we are running an accelerated animation, set a flag in the style
+ // to indicate it. This can be used to make sure we get an updated
+ // style for hit testing, etc.
+ animatedStyle->setIsRunningAcceleratedAnimation();
+#endif
+ }
}
}
+void KeyframeAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle)
+{
+ // Get the from/to styles and progress between
+ const RenderStyle* fromStyle = 0;
+ const RenderStyle* toStyle = 0;
+ double progress;
+ getKeyframeAnimationInterval(fromStyle, toStyle, progress);
+
+ // If either style is 0 we have an invalid case
+ if (!fromStyle || !toStyle)
+ return;
+
+ if (!animatedStyle)
+ animatedStyle = RenderStyle::clone(m_object->style());
+
+ HashSet<int>::const_iterator endProperties = m_keyframes.endProperties();
+ for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it)
+ blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress);
+}
+
bool KeyframeAnimation::hasAnimationForProperty(int property) const
{
HashSet<int>::const_iterator end = m_keyframes.endProperties();
@@ -148,14 +189,38 @@ bool KeyframeAnimation::hasAnimationForProperty(int property) const
return false;
}
-void KeyframeAnimation::endAnimation(bool)
+bool KeyframeAnimation::startAnimation(double beginTime)
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_object && m_object->hasLayer()) {
+ RenderLayer* layer = toRenderBoxModelObject(m_object)->layer();
+ if (layer->isComposited())
+ return layer->backing()->startAnimation(beginTime, m_animation.get(), m_keyframes);
+ }
+#else
+ UNUSED_PARAM(beginTime);
+#endif
+ return false;
+}
+
+void KeyframeAnimation::endAnimation(bool reset)
{
- // Restore the original (unanimated) style
- if (m_object)
- setChanged(m_object->element());
+ if (m_object) {
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_object->hasLayer()) {
+ RenderLayer* layer = toRenderBoxModelObject(m_object)->layer();
+ if (layer->isComposited())
+ layer->backing()->animationFinished(m_keyframes.animationName(), 0, reset);
+ }
+#else
+ UNUSED_PARAM(reset);
+#endif
+ // Restore the original (unanimated) style
+ setChanged(m_object->node());
+ }
}
-bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType)
+bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType) const
{
return m_object->document()->hasListenerType(listenerType);
}
@@ -201,7 +266,7 @@ bool KeyframeAnimation::sendAnimationEvent(const AtomicString& eventType, double
return false;
// Schedule event handling
- m_object->animation()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime);
+ m_compAnim->animationControllerPriv()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime);
// Restore the original (unanimated) style
if (eventType == eventNames().webkitAnimationEndEvent && element->renderer())
@@ -287,4 +352,31 @@ void KeyframeAnimation::validateTransformFunctionList()
m_transformFunctionListValid = true;
}
+double KeyframeAnimation::willNeedService()
+{
+ double t = AnimationBase::willNeedService();
+#if USE(ACCELERATED_COMPOSITING)
+ if (t != 0 || preActive())
+ return t;
+
+ // A return value of 0 means we need service. But if we only have accelerated animations we
+ // only need service at the end of the transition
+ HashSet<int>::const_iterator endProperties = m_keyframes.endProperties();
+ bool acceleratedPropertiesOnly = true;
+
+ for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) {
+ if (!animationOfPropertyIsAccelerated(*it) || isFallbackAnimating()) {
+ acceleratedPropertiesOnly = false;
+ break;
+ }
+ }
+
+ if (acceleratedPropertiesOnly) {
+ bool isLooping;
+ getTimeToNextEvent(t, isLooping);
+ }
+#endif
+ return t;
+}
+
} // namespace WebCore
diff --git a/WebCore/page/animation/KeyframeAnimation.h b/WebCore/page/animation/KeyframeAnimation.h
index 5c3176c..1090e5b 100644
--- a/WebCore/page/animation/KeyframeAnimation.h
+++ b/WebCore/page/animation/KeyframeAnimation.h
@@ -44,8 +44,9 @@ public:
{
return adoptRef(new KeyframeAnimation(animation, renderer, index, compositeAnimation, unanimatedStyle));
};
-
- virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, const RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle);
+
+ virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle);
+ virtual void getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle);
const AtomicString& name() const { return m_keyframes.animationName(); }
int index() const { return m_index; }
@@ -56,16 +57,19 @@ public:
void setUnanimatedStyle(PassRefPtr<RenderStyle> style) { m_unanimatedStyle = style; }
RenderStyle* unanimatedStyle() const { return m_unanimatedStyle.get(); }
+ virtual double willNeedService();
+
protected:
virtual void onAnimationStart(double elapsedTime);
virtual void onAnimationIteration(double elapsedTime);
virtual void onAnimationEnd(double elapsedTime);
+ virtual bool startAnimation(double beginTime);
virtual void endAnimation(bool reset);
virtual void overrideAnimations();
virtual void resumeOverriddenAnimations();
- bool shouldSendEventForListener(Document::ListenerType inListenerType);
+ bool shouldSendEventForListener(Document::ListenerType inListenerType) const;
bool sendAnimationEvent(const AtomicString&, double elapsedTime);
virtual bool affectsProperty(int) const;
@@ -76,6 +80,9 @@ private:
KeyframeAnimation(const Animation* animation, RenderObject*, int index, CompositeAnimation*, RenderStyle* unanimatedStyle);
virtual ~KeyframeAnimation();
+ // Get the styles surrounding the current animation time and the progress between them
+ void getKeyframeAnimationInterval(const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& progress) const;
+
// The keyframes that we are blending.
KeyframeList m_keyframes;
diff --git a/WebCore/page/chromium/AccessibilityObjectWrapper.h b/WebCore/page/chromium/AccessibilityObjectWrapper.h
index 9920e4d..6420b32 100644
--- a/WebCore/page/chromium/AccessibilityObjectWrapper.h
+++ b/WebCore/page/chromium/AccessibilityObjectWrapper.h
@@ -39,7 +39,11 @@ namespace WebCore {
protected:
AccessibilityObjectWrapper(AccessibilityObject* obj)
- : RefCounted<AccessibilityObjectWrapper>(0), m_object(obj) { }
+ : m_object(obj)
+ {
+ // FIXME: Remove this once our immediate subclass no longer uses COM.
+ m_refCount = 0;
+ }
AccessibilityObjectWrapper() : m_object(0) { }
AccessibilityObject* m_object;
diff --git a/WebCore/page/chromium/EventHandlerChromium.cpp b/WebCore/page/chromium/EventHandlerChromium.cpp
index 883bece..0cfc12d 100644
--- a/WebCore/page/chromium/EventHandlerChromium.cpp
+++ b/WebCore/page/chromium/EventHandlerChromium.cpp
@@ -62,7 +62,7 @@ bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m
if (m_frame->selection()->contains(p)) {
VisiblePosition visiblePos(
mev.targetNode()->renderer()->positionForPoint(mev.localPoint()));
- Selection newSelection(visiblePos);
+ VisibleSelection newSelection(visiblePos);
if (m_frame->shouldChangeSelection(newSelection))
m_frame->selection()->setSelection(newSelection);
}
@@ -148,7 +148,11 @@ bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget)
unsigned EventHandler::accessKeyModifiers()
{
+#if PLATFORM(DARWIN)
+ return PlatformKeyboardEvent::CtrlKey | PlatformKeyboardEvent::AltKey;
+#else
return PlatformKeyboardEvent::AltKey;
+#endif
}
} // namespace WebCore
diff --git a/WebCore/page/chromium/FrameChromium.cpp b/WebCore/page/chromium/FrameChromium.cpp
index 1e4ed16..d85fbcc 100644
--- a/WebCore/page/chromium/FrameChromium.cpp
+++ b/WebCore/page/chromium/FrameChromium.cpp
@@ -79,7 +79,7 @@ void computePageRectsForFrame(Frame* frame, const IntRect& printRect, float head
float printedPagesHeight = 0.0f;
do {
float proposedBottom = min(docHeight, printedPagesHeight + pageHeight);
- frame->adjustPageHeight(&proposedBottom, printedPagesHeight, proposedBottom, printedPagesHeight);
+ frame->view()->adjustPageHeight(&proposedBottom, printedPagesHeight, proposedBottom, printedPagesHeight);
currPageHeight = max(1.0f, proposedBottom - printedPagesHeight);
pages.append(IntRect(0, printedPagesHeight, currPageWidth, currPageHeight));
diff --git a/WebCore/page/gtk/AccessibilityObjectWrapperAtk.cpp b/WebCore/page/gtk/AccessibilityObjectWrapperAtk.cpp
index c1a405e..84f3d34 100644
--- a/WebCore/page/gtk/AccessibilityObjectWrapperAtk.cpp
+++ b/WebCore/page/gtk/AccessibilityObjectWrapperAtk.cpp
@@ -110,7 +110,7 @@ static const gchar* webkit_accessible_get_name(AtkObject* object)
{
// TODO: Deal with later changes.
if (!object->name)
- atk_object_set_name(object, core(object)->title().utf8().data());
+ atk_object_set_name(object, core(object)->stringValue().utf8().data());
return object->name;
}
@@ -650,7 +650,7 @@ void webkit_accessible_detach(WebKitAccessible* accessible)
// detachment.
// FIXME: Using fallbackCache->get(ListBoxOptionRole) is a hack.
- accessible->m_object = fallbackCache->get(ListBoxOptionRole);
+ accessible->m_object = fallbackCache->getOrCreate(ListBoxOptionRole);
}
}
diff --git a/WebCore/page/mac/AXObjectCacheMac.mm b/WebCore/page/mac/AXObjectCacheMac.mm
index d5ce8f3..936d9de 100644
--- a/WebCore/page/mac/AXObjectCacheMac.mm
+++ b/WebCore/page/mac/AXObjectCacheMac.mm
@@ -58,9 +58,9 @@ void AXObjectCache::postNotification(RenderObject* renderer, const String& messa
// notifications for text input objects are sent to that object
// all others are sent to the top WebArea
- RefPtr<AccessibilityObject> obj = get(renderer)->observableObject();
+ RefPtr<AccessibilityObject> obj = getOrCreate(renderer)->observableObject();
if (!obj)
- obj = get(renderer->document()->renderer());
+ obj = getOrCreate(renderer->document()->renderer());
if (!obj)
return;
@@ -74,7 +74,7 @@ void AXObjectCache::postNotificationToElement(RenderObject* renderer, const Stri
if (!renderer)
return;
- RefPtr<AccessibilityObject> obj = get(renderer);
+ RefPtr<AccessibilityObject> obj = getOrCreate(renderer);
if (!obj)
return;
diff --git a/WebCore/page/mac/AccessibilityObjectWrapper.h b/WebCore/page/mac/AccessibilityObjectWrapper.h
index 5a55fe0..3b584a9 100644
--- a/WebCore/page/mac/AccessibilityObjectWrapper.h
+++ b/WebCore/page/mac/AccessibilityObjectWrapper.h
@@ -25,8 +25,11 @@
* (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 <wtf/RefPtr.h>
+
+#ifndef AccessibilityObjectWrapper_h
+#define AccessibilityObjectWrapper_h
+
+#import <wtf/RefPtr.h>
#ifdef __OBJC__
@class WebCoreTextMarker;
@@ -53,3 +56,5 @@ namespace WebCore {
- (NSView*)attachmentView;
@end
+
+#endif // AccessibilityObjectWrapper_h
diff --git a/WebCore/page/mac/AccessibilityObjectWrapper.mm b/WebCore/page/mac/AccessibilityObjectWrapper.mm
index 1e28f00..1e596eb 100644
--- a/WebCore/page/mac/AccessibilityObjectWrapper.mm
+++ b/WebCore/page/mac/AccessibilityObjectWrapper.mm
@@ -181,9 +181,11 @@ static WebCoreTextMarker* textMarkerForVisiblePosition(const VisiblePosition& vi
if (!domNode)
return nil;
- if (domNode->isHTMLElement())
- if (static_cast<HTMLElement*>(domNode)->isPasswordField())
+ if (domNode->isHTMLElement()) {
+ InputElement* inputElement = toInputElement(static_cast<Element*>(domNode));
+ if (inputElement && inputElement->isPasswordField())
return nil;
+ }
// locate the renderer, which must exist for a visible dom node
RenderObject* renderer = domNode->renderer();
@@ -191,7 +193,7 @@ static WebCoreTextMarker* textMarkerForVisiblePosition(const VisiblePosition& vi
// find or create an accessibility object for this renderer
AXObjectCache* cache = renderer->document()->axObjectCache();
- RefPtr<AccessibilityObject> obj = cache->get(renderer);
+ RefPtr<AccessibilityObject> obj = cache->getOrCreate(renderer);
// create a text marker, adding an ID for the AccessibilityObject if needed
TextMarkerData textMarkerData;
@@ -201,7 +203,7 @@ static WebCoreTextMarker* textMarkerForVisiblePosition(const VisiblePosition& vi
bzero(&textMarkerData, sizeof(TextMarkerData));
textMarkerData.axID = obj.get()->axObjectID();
textMarkerData.node = domNode;
- textMarkerData.offset = deepPos.offset();
+ textMarkerData.offset = deepPos.m_offset;
textMarkerData.affinity = visiblePos.affinity();
return [[WebCoreViewFactory sharedFactory] textMarkerWithBytes:&textMarkerData length:sizeof(textMarkerData)];
}
@@ -226,7 +228,7 @@ static VisiblePosition visiblePositionForTextMarker(WebCoreTextMarker* textMarke
if (!cache->isIDinUse(textMarkerData.axID))
return VisiblePosition();
- if (deepPos.node() != textMarkerData.node || deepPos.offset() != textMarkerData.offset)
+ if (deepPos.node() != textMarkerData.node || deepPos.m_offset != textMarkerData.offset)
return VisiblePosition();
return visiblePos;
@@ -374,7 +376,7 @@ static int blockquoteLevel(RenderObject* renderer)
return 0;
int result = 0;
- for (Node* node = renderer->element(); node; node = node->parent()) {
+ for (Node* node = renderer->node(); node; node = node->parent()) {
if (node->hasTagName(blockquoteTag))
result += 1;
}
@@ -423,7 +425,7 @@ static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString,
static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
{
- int parentHeadingLevel = AccessibilityRenderObject::headingLevel(renderer->parent()->element());
+ int parentHeadingLevel = AccessibilityRenderObject::headingLevel(renderer->parent()->node());
if (parentHeadingLevel)
[attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
@@ -437,7 +439,7 @@ static AccessibilityObject* AXLinkElementForNode(Node* node)
if (!obj)
return 0;
- RefPtr<AccessibilityObject> axObj = obj->document()->axObjectCache()->get(obj);
+ RefPtr<AccessibilityObject> axObj = obj->document()->axObjectCache()->getOrCreate(obj);
Element* anchor = axObj->anchorElement();
if (!anchor)
return 0;
@@ -446,7 +448,7 @@ static AccessibilityObject* AXLinkElementForNode(Node* node)
if (!anchorRenderer)
return 0;
- return anchorRenderer->document()->axObjectCache()->get(anchorRenderer);
+ return anchorRenderer->document()->axObjectCache()->getOrCreate(anchorRenderer);
}
static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
@@ -515,7 +517,7 @@ static NSString* nsStringForReplacedNode(Node* replacedNode)
}
// create an AX object, but skip it if it is not supposed to be seen
- RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document()->axObjectCache()->get(replacedNode->renderer());
+ RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
if (obj->accessibilityIsIgnored())
return nil;
@@ -561,7 +563,7 @@ static NSString* nsStringForReplacedNode(Node* replacedNode)
[attrString setAttributes:nil range:attrStringRange];
// add the attachment attribute
- AccessibilityObject* obj = replacedNode->renderer()->document()->axObjectCache()->get(replacedNode->renderer());
+ AccessibilityObject* obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
}
}
@@ -580,6 +582,9 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi
- (NSArray*)accessibilityActionNames
{
+ if (!m_object)
+ return nil;
+
m_object->updateBackingStore();
static NSArray* actionElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityPressAction, NSAccessibilityShowMenuAction, nil];
@@ -601,6 +606,9 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi
- (NSArray*)accessibilityAttributeNames
{
+ if (!m_object)
+ return nil;
+
m_object->updateBackingStore();
if (m_object->isAttachment())
@@ -871,7 +879,7 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi
static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
{
unsigned length = [array count];
- vector.reserveCapacity(length);
+ vector.reserveInitialCapacity(length);
for (unsigned i = 0; i < length; ++i) {
AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
if (obj)
@@ -884,16 +892,23 @@ static NSMutableArray* convertToNSArray(const AccessibilityObject::Accessibility
unsigned length = vector.size();
NSMutableArray* array = [NSMutableArray arrayWithCapacity: length];
for (unsigned i = 0; i < length; ++i) {
- ASSERT(vector[i]->wrapper());
- if (vector[i]->wrapper())
- [array addObject:vector[i]->wrapper()];
+ AccessibilityObjectWrapper* wrapper = vector[i]->wrapper();
+ ASSERT(wrapper);
+ if (wrapper) {
+ // we want to return the attachment view instead of the object representing the attachment.
+ // otherwise, we get palindrome errors in the AX hierarchy
+ if (vector[i]->isAttachment() && [wrapper attachmentView])
+ [array addObject:[wrapper attachmentView]];
+ else
+ [array addObject:wrapper];
+ }
}
return array;
}
- (WebCoreTextMarkerRange*)textMarkerRangeForSelection
{
- Selection selection = m_object->selection();
+ VisibleSelection selection = m_object->selection();
if (selection.isNone())
return nil;
return textMarkerRangeFromVisiblePositions(selection.visibleStart(), selection.visibleEnd());
@@ -1436,6 +1451,9 @@ static NSString* roleValueToNSString(AccessibilityRole value)
- (id)accessibilityFocusedUIElement
{
+ if (!m_object)
+ return nil;
+
m_object->updateBackingStore();
RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();
@@ -1448,6 +1466,9 @@ static NSString* roleValueToNSString(AccessibilityRole value)
- (id)accessibilityHitTest:(NSPoint)point
{
+ if (!m_object)
+ return nil;
+
m_object->updateBackingStore();
RefPtr<AccessibilityObject> axObject = m_object->doAccessibilityHitTest(IntPoint(point));
@@ -1458,6 +1479,9 @@ static NSString* roleValueToNSString(AccessibilityRole value)
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
{
+ if (!m_object)
+ return nil;
+
m_object->updateBackingStore();
if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
@@ -1494,6 +1518,9 @@ static NSString* roleValueToNSString(AccessibilityRole value)
// Registering an object is also required for observing notifications. Only registered objects can be observed.
- (BOOL)accessibilityIsIgnored
{
+ if (!m_object)
+ return nil;
+
m_object->updateBackingStore();
if (m_object->isAttachment())
@@ -1503,6 +1530,9 @@ static NSString* roleValueToNSString(AccessibilityRole value)
- (NSArray* )accessibilityParameterizedAttributeNames
{
+ if (!m_object)
+ return nil;
+
m_object->updateBackingStore();
if (m_object->isAttachment())
@@ -1585,6 +1615,9 @@ static NSString* roleValueToNSString(AccessibilityRole value)
- (void)accessibilityPerformPressAction
{
+ if (!m_object)
+ return;
+
m_object->updateBackingStore();
if (m_object->isAttachment())
@@ -1631,6 +1664,9 @@ static NSString* roleValueToNSString(AccessibilityRole value)
- (void)accessibilityPerformAction:(NSString*)action
{
+ if (!m_object)
+ return;
+
m_object->updateBackingStore();
if ([action isEqualToString:NSAccessibilityPressAction])
@@ -1642,6 +1678,9 @@ static NSString* roleValueToNSString(AccessibilityRole value)
- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
{
+ if (!m_object)
+ return;
+
m_object->updateBackingStore();
WebCoreTextMarkerRange* textMarkerRange = nil;
@@ -1721,7 +1760,7 @@ static RenderObject* rendererForView(NSView* view)
if (!renderer)
return nil;
- AccessibilityObject* obj = renderer->document()->axObjectCache()->get(renderer);
+ AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);
if (obj)
return obj->parentObjectUnignored()->wrapper();
return nil;
@@ -2013,6 +2052,9 @@ static RenderObject* rendererForView(NSView* view)
// API that AppKit uses for faster access
- (NSUInteger)accessibilityIndexOfChild:(id)child
{
+ if (!m_object)
+ return NSNotFound;
+
m_object->updateBackingStore();
const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();
@@ -2022,7 +2064,8 @@ static RenderObject* rendererForView(NSView* view)
unsigned count = children.size();
for (unsigned k = 0; k < count; ++k) {
- if (children[k]->wrapper() == child)
+ AccessibilityObjectWrapper* wrapper = children[k]->wrapper();
+ if (wrapper == child || (children[k]->isAttachment() && [wrapper attachmentView] == child))
return k;
}
@@ -2031,6 +2074,9 @@ static RenderObject* rendererForView(NSView* view)
- (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute
{
+ if (!m_object)
+ return 0;
+
m_object->updateBackingStore();
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
@@ -2046,6 +2092,9 @@ static RenderObject* rendererForView(NSView* view)
- (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount
{
+ if (!m_object)
+ return nil;
+
m_object->updateBackingStore();
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
@@ -2070,8 +2119,16 @@ static RenderObject* rendererForView(NSView* view)
unsigned available = min(childCount - index, maxCount);
NSMutableArray *subarray = [NSMutableArray arrayWithCapacity:available];
- for (unsigned added = 0; added < available; ++index, ++added)
- [subarray addObject:children[index]->wrapper()];
+ for (unsigned added = 0; added < available; ++index, ++added) {
+ AccessibilityObjectWrapper* wrapper = children[index]->wrapper();
+ if (wrapper) {
+ // The attachment view should be returned, otherwise AX palindrome errors occur.
+ if (children[index]->isAttachment() && [wrapper attachmentView])
+ [subarray addObject:[wrapper attachmentView]];
+ else
+ [subarray addObject:wrapper];
+ }
+ }
return subarray;
}
diff --git a/WebCore/page/mac/EventHandlerMac.mm b/WebCore/page/mac/EventHandlerMac.mm
index 5d09843..33d1c5f 100644
--- a/WebCore/page/mac/EventHandlerMac.mm
+++ b/WebCore/page/mac/EventHandlerMac.mm
@@ -83,10 +83,10 @@ PassRefPtr<KeyboardEvent> EventHandler::currentKeyboardEvent() const
case NSKeyDown: {
PlatformKeyboardEvent platformEvent(event);
platformEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::RawKeyDown);
- return KeyboardEvent::create(platformEvent, m_frame->document() ? m_frame->document()->defaultView() : 0);
+ return KeyboardEvent::create(platformEvent, m_frame->document()->defaultView());
}
case NSKeyUp:
- return KeyboardEvent::create(event, m_frame->document() ? m_frame->document()->defaultView() : 0);
+ return KeyboardEvent::create(event, m_frame->document()->defaultView());
default:
return 0;
}
@@ -140,8 +140,6 @@ bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
}
Document* document = m_frame->document();
- if (!document)
- return false;
// RSS view needs arrow key keypress events.
if (isSafari && document->url().protocolIs("feed") || document->url().protocolIs("feeds"))
diff --git a/WebCore/page/mac/FrameMac.mm b/WebCore/page/mac/FrameMac.mm
index 84d7549..f360511 100644
--- a/WebCore/page/mac/FrameMac.mm
+++ b/WebCore/page/mac/FrameMac.mm
@@ -156,7 +156,7 @@ NSString* Frame::searchForNSLabelsAboveCell(RegularExpression* regExp, HTMLTable
if (cellAboveRenderer) {
HTMLTableCellElement* aboveCell =
- static_cast<HTMLTableCellElement*>(cellAboveRenderer->element());
+ static_cast<HTMLTableCellElement*>(cellAboveRenderer->node());
if (aboveCell) {
// search within the above cell we found for a match
@@ -490,8 +490,6 @@ void Frame::setUseSecureKeyboardEntry(bool enable)
NSMutableDictionary* Frame::dashboardRegionsDictionary()
{
Document* doc = document();
- if (!doc)
- return nil;
const Vector<DashboardRegionValue>& regions = doc->dashboardRegions();
size_t n = regions.size();
@@ -537,7 +535,7 @@ void Frame::setUserStyleSheetLocation(const KURL& url)
{
delete m_userStyleSheetLoader;
m_userStyleSheetLoader = 0;
- if (m_doc && m_doc->docLoader())
+ if (m_doc->docLoader())
m_userStyleSheetLoader = new UserStyleSheetLoader(m_doc, url.string());
}
@@ -545,8 +543,7 @@ void Frame::setUserStyleSheet(const String& styleSheet)
{
delete m_userStyleSheetLoader;
m_userStyleSheetLoader = 0;
- if (m_doc)
- m_doc->setUserStyleSheet(styleSheet);
+ m_doc->setUserStyleSheet(styleSheet);
}
} // namespace WebCore
diff --git a/WebCore/page/win/FrameWin.cpp b/WebCore/page/win/FrameWin.cpp
index fef1ffa..db55d30 100644
--- a/WebCore/page/win/FrameWin.cpp
+++ b/WebCore/page/win/FrameWin.cpp
@@ -81,7 +81,7 @@ void computePageRectsForFrame(Frame* frame, const IntRect& printRect, float head
float printedPagesHeight = 0.0f;
do {
float proposedBottom = min(docHeight, printedPagesHeight + pageHeight);
- frame->adjustPageHeight(&proposedBottom, printedPagesHeight, proposedBottom, printedPagesHeight);
+ frame->view()->adjustPageHeight(&proposedBottom, printedPagesHeight, proposedBottom, printedPagesHeight);
currPageHeight = max(1.0f, proposedBottom - printedPagesHeight);
pages.append(IntRect(0, printedPagesHeight, currPageWidth, currPageHeight));