diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2009-06-15 09:06:43 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-06-15 09:31:31 (GMT) |
commit | c411f16870f112c3407c28c22b617f613a82cff4 (patch) | |
tree | 29a1bcd590c8b31af2aab445bfe8a978dc5bf582 /src/3rdparty/webkit/WebCore/page | |
parent | 3d77b56b32a0c53ec0bbfaa07236fedb900ff336 (diff) | |
download | Qt-c411f16870f112c3407c28c22b617f613a82cff4.zip Qt-c411f16870f112c3407c28c22b617f613a82cff4.tar.gz Qt-c411f16870f112c3407c28c22b617f613a82cff4.tar.bz2 |
Updated WebKit from /home/shausman/src/webkit/trunk to qtwebkit-4.6-snapshot-15062009 ( 65232bf00dc494ebfd978f998c88f58d18ecce1e )
Diffstat (limited to 'src/3rdparty/webkit/WebCore/page')
100 files changed, 5507 insertions, 9520 deletions
diff --git a/src/3rdparty/webkit/WebCore/page/AXObjectCache.cpp b/src/3rdparty/webkit/WebCore/page/AXObjectCache.cpp deleted file mode 100644 index d9c4c9a..0000000 --- a/src/3rdparty/webkit/WebCore/page/AXObjectCache.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AXObjectCache.h" - -#include "AccessibilityList.h" -#include "AccessibilityListBox.h" -#include "AccessibilityListBoxOption.h" -#include "AccessibilityImageMapLink.h" -#include "AccessibilityRenderObject.h" -#include "AccessibilityTable.h" -#include "AccessibilityTableCell.h" -#include "AccessibilityTableColumn.h" -#include "AccessibilityTableHeaderContainer.h" -#include "AccessibilityTableRow.h" -#include "HTMLNames.h" -#include "RenderObject.h" - -#include <wtf/PassRefPtr.h> - -namespace WebCore { - -using namespace HTMLNames; - -bool AXObjectCache::gAccessibilityEnabled = false; -bool AXObjectCache::gAccessibilityEnhancedUserInterfaceEnabled = false; - -AXObjectCache::~AXObjectCache() -{ - HashMap<AXID, RefPtr<AccessibilityObject> >::iterator end = m_objects.end(); - for (HashMap<AXID, RefPtr<AccessibilityObject> >::iterator it = m_objects.begin(); it != end; ++it) { - AccessibilityObject* obj = (*it).second.get(); - detachWrapper(obj); - obj->detach(); - } -} - -AccessibilityObject* AXObjectCache::get(RenderObject* renderer) -{ - if (!renderer) - return 0; - - RefPtr<AccessibilityObject> obj = 0; - AXID axID = m_renderObjectMapping.get(renderer); - ASSERT(!HashTraits<AXID>::isDeletedValue(axID)); - - if (axID) - obj = m_objects.get(axID).get(); - - Node* element = renderer->element(); - if (!obj) { - if (renderer->isListBox()) - obj = AccessibilityListBox::create(renderer); - else if (element && (element->hasTagName(ulTag) || element->hasTagName(olTag) || element->hasTagName(dlTag))) - obj = AccessibilityList::create(renderer); - else if (renderer->isTable()) - obj = AccessibilityTable::create(renderer); - else if (renderer->isTableRow()) - obj = AccessibilityTableRow::create(renderer); - else if (renderer->isTableCell()) - obj = AccessibilityTableCell::create(renderer); - else - obj = AccessibilityRenderObject::create(renderer); - - getAXID(obj.get()); - - m_renderObjectMapping.set(renderer, obj.get()->axObjectID()); - m_objects.set(obj.get()->axObjectID(), obj); - attachWrapper(obj.get()); - } - - return obj.get(); -} - -AccessibilityObject* AXObjectCache::get(AccessibilityRole role) -{ - RefPtr<AccessibilityObject> obj = 0; - - // will be filled in... - switch (role) { - case ListBoxOptionRole: - obj = AccessibilityListBoxOption::create(); - break; - case ImageMapLinkRole: - obj = AccessibilityImageMapLink::create(); - break; - case ColumnRole: - obj = AccessibilityTableColumn::create(); - break; - case TableHeaderContainerRole: - obj = AccessibilityTableHeaderContainer::create(); - break; - default: - obj = 0; - } - - if (obj) - getAXID(obj.get()); - else - return 0; - - m_objects.set(obj->axObjectID(), obj); - attachWrapper(obj.get()); - return obj.get(); -} - -void AXObjectCache::remove(AXID axID) -{ - if (!axID) - return; - - // first fetch object to operate some cleanup functions on it - AccessibilityObject* obj = m_objects.get(axID).get(); - if (!obj) - return; - - detachWrapper(obj); - obj->detach(); - removeAXID(obj); - - // finally remove the object - if (!m_objects.take(axID)) { - return; - } - - ASSERT(m_objects.size() >= m_idsInUse.size()); -} - -void AXObjectCache::remove(RenderObject* renderer) -{ - if (!renderer) - return; - - AXID axID = m_renderObjectMapping.get(renderer); - remove(axID); - m_renderObjectMapping.remove(renderer); -} - -AXID AXObjectCache::getAXID(AccessibilityObject* obj) -{ - // check for already-assigned ID - AXID objID = obj->axObjectID(); - if (objID) { - ASSERT(m_idsInUse.contains(objID)); - return objID; - } - - // generate a new ID - static AXID lastUsedID = 0; - objID = lastUsedID; - do - ++objID; - while (objID == 0 || HashTraits<AXID>::isDeletedValue(objID) || m_idsInUse.contains(objID)); - m_idsInUse.add(objID); - lastUsedID = objID; - obj->setAXObjectID(objID); - - return objID; -} - -void AXObjectCache::removeAXID(AccessibilityObject* obj) -{ - AXID objID = obj->axObjectID(); - if (objID == 0) - return; - ASSERT(!HashTraits<AXID>::isDeletedValue(objID)); - ASSERT(m_idsInUse.contains(objID)); - obj->setAXObjectID(0); - m_idsInUse.remove(objID); -} - -void AXObjectCache::childrenChanged(RenderObject* renderer) -{ - if (!renderer) - return; - - AXID axID = m_renderObjectMapping.get(renderer); - if (!axID) - return; - - AccessibilityObject* obj = m_objects.get(axID).get(); - if (obj) - obj->childrenChanged(); -} - -#if HAVE(ACCESSIBILITY) -void AXObjectCache::selectedChildrenChanged(RenderObject* renderer) -{ - postNotificationToElement(renderer, "AXSelectedChildrenChanged"); -} -#endif - -#if HAVE(ACCESSIBILITY) -void AXObjectCache::handleActiveDescendantChanged(RenderObject* renderer) -{ - if (!renderer) - return; - AccessibilityObject* obj = get(renderer); - if (obj) - obj->handleActiveDescendantChanged(); -} - -void AXObjectCache::handleAriaRoleChanged(RenderObject* renderer) -{ - if (!renderer) - return; - AccessibilityObject* obj = get(renderer); - if (obj && obj->isAccessibilityRenderObject()) - static_cast<AccessibilityRenderObject*>(obj)->setAriaRole(); -} -#endif - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AXObjectCache.h b/src/3rdparty/webkit/WebCore/page/AXObjectCache.h deleted file mode 100644 index 5e95f74..0000000 --- a/src/3rdparty/webkit/WebCore/page/AXObjectCache.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2003, 2006, 2007, 2008 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 AXObjectCache_h -#define AXObjectCache_h - -#include "AccessibilityObject.h" -#include <limits.h> -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/RefPtr.h> - -#ifdef __OBJC__ -@class WebCoreTextMarker; -#else -class WebCoreTextMarker; -#endif - -namespace WebCore { - - class RenderObject; - class String; - class VisiblePosition; - class AccessibilityObject; - class Node; - - typedef unsigned AXID; - - struct TextMarkerData { - AXID axID; - Node* node; - int offset; - EAffinity affinity; - }; - - class AXObjectCache { - public: - ~AXObjectCache(); - - // to be used with render objects - AccessibilityObject* get(RenderObject*); - - // used for objects without backing elements - AccessibilityObject* get(AccessibilityRole); - - void remove(RenderObject*); - void remove(AXID); - - void detachWrapper(AccessibilityObject*); - void attachWrapper(AccessibilityObject*); - void postNotification(RenderObject*, const String&); - void postNotificationToElement(RenderObject*, const String&); - void childrenChanged(RenderObject*); - void selectedChildrenChanged(RenderObject*); - void handleActiveDescendantChanged(RenderObject*); - void handleAriaRoleChanged(RenderObject*); - void handleFocusedUIElementChanged(); - static void enableAccessibility() { gAccessibilityEnabled = true; } - static void enableEnhancedUserInterfaceAccessibility() { gAccessibilityEnhancedUserInterfaceEnabled = true; } - - static bool accessibilityEnabled() { return gAccessibilityEnabled; } - static bool accessibilityEnhancedUserInterfaceEnabled() { return gAccessibilityEnhancedUserInterfaceEnabled; } - - void removeAXID(AccessibilityObject*); - bool isIDinUse(AXID id) const { return m_idsInUse.contains(id); } - - private: - HashMap<AXID, RefPtr<AccessibilityObject> > m_objects; - HashMap<RenderObject*, AXID> m_renderObjectMapping; - static bool gAccessibilityEnabled; - static bool gAccessibilityEnhancedUserInterfaceEnabled; - - HashSet<AXID> m_idsInUse; - - AXID getAXID(AccessibilityObject*); - }; - -#if !HAVE(ACCESSIBILITY) - inline void AXObjectCache::handleActiveDescendantChanged(RenderObject*) { } - inline void AXObjectCache::handleAriaRoleChanged(RenderObject*) { } - inline void AXObjectCache::handleFocusedUIElementChanged() { } - inline void AXObjectCache::detachWrapper(AccessibilityObject*) { } - inline void AXObjectCache::attachWrapper(AccessibilityObject*) { } - inline void AXObjectCache::selectedChildrenChanged(RenderObject*) { } - inline void AXObjectCache::postNotification(RenderObject*, const String&) { } - inline void AXObjectCache::postNotificationToElement(RenderObject*, const String&) { } -#endif - -} - -#endif diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityImageMapLink.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityImageMapLink.cpp deleted file mode 100644 index 5557446..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityImageMapLink.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AccessibilityImageMapLink.h" - -#include "AccessibilityRenderObject.h" -#include "AXObjectCache.h" -#include "Document.h" -#include "HTMLNames.h" -#include "IntRect.h" -#include "RenderObject.h" - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityImageMapLink::AccessibilityImageMapLink() - : m_areaElement(0), - m_mapElement(0) -{ -} - -AccessibilityImageMapLink::~AccessibilityImageMapLink() -{ -} - -PassRefPtr<AccessibilityImageMapLink> AccessibilityImageMapLink::create() -{ - return adoptRef(new AccessibilityImageMapLink()); -} - -AccessibilityObject* AccessibilityImageMapLink::parentObject() const -{ - if (m_parent) - return m_parent; - - if (!m_mapElement || !m_mapElement->renderer()) - return 0; - - return m_mapElement->document()->axObjectCache()->get(m_mapElement->renderer()); -} - -Element* AccessibilityImageMapLink::actionElement() const -{ - return anchorElement(); -} - -Element* AccessibilityImageMapLink::anchorElement() const -{ - return m_areaElement; -} - -String AccessibilityImageMapLink::accessibilityDescription() const -{ - if (!m_areaElement) - return String(); - - const AtomicString& alt = m_areaElement->getAttribute(altAttr); - if (!alt.isEmpty()) - return alt; - - return String(); -} - -String AccessibilityImageMapLink::title() const -{ - if (!m_areaElement) - return String(); - - const AtomicString& title = m_areaElement->getAttribute(titleAttr); - if (!title.isEmpty()) - return title; - const AtomicString& summary = m_areaElement->getAttribute(summaryAttr); - if (!summary.isEmpty()) - return summary; - - return String(); -} - -IntRect AccessibilityImageMapLink::elementRect() const -{ - if (!m_mapElement || !m_areaElement) - return IntRect(); - - RenderObject* renderer; - if (m_parent && m_parent->isAccessibilityRenderObject()) - renderer = static_cast<AccessibilityRenderObject*>(m_parent)->renderer(); - else - renderer = m_mapElement->renderer(); - - if (!renderer) - return IntRect(); - - return m_areaElement->getRect(renderer); -} - -IntSize AccessibilityImageMapLink::size() const -{ - return elementRect().size(); -} - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityImageMapLink.h b/src/3rdparty/webkit/WebCore/page/AccessibilityImageMapLink.h deleted file mode 100644 index 7fc8d3c..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityImageMapLink.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2008 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 AccessibilityImageMapLink_h -#define AccessibilityImageMapLink_h - -#include "AccessibilityObject.h" -#include "HTMLAreaElement.h" -#include "HTMLMapElement.h" - -namespace WebCore { - -class AccessibilityImageMapLink : public AccessibilityObject { - -private: - AccessibilityImageMapLink(); -public: - static PassRefPtr<AccessibilityImageMapLink> create(); - virtual ~AccessibilityImageMapLink(); - - void setHTMLAreaElement(HTMLAreaElement* element) { m_areaElement = element; } - void setHTMLMapElement(HTMLMapElement* element) { m_mapElement = element; } - void setParent(AccessibilityObject* parent) { m_parent = parent; } - - virtual AccessibilityRole roleValue() const { return WebCoreLinkRole; } - virtual bool accessibilityIsIgnored() const { return false; } - - virtual AccessibilityObject* parentObject() const; - virtual Element* anchorElement() const; - virtual Element* actionElement() const; - - virtual bool isLink() const { return true; } - virtual String title() const; - virtual String accessibilityDescription() const; - - virtual IntSize size() const; - virtual IntRect elementRect() const; - -private: - HTMLAreaElement* m_areaElement; - HTMLMapElement* m_mapElement; - AccessibilityObject* m_parent; -}; - -} // namespace WebCore - -#endif // AccessibilityImageMapLink_h diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityList.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityList.cpp deleted file mode 100644 index ad71ff4..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityList.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AccessibilityList.h" - -#include "AXObjectCache.h" -#include "HTMLNames.h" -#include "RenderObject.h" - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityList::AccessibilityList(RenderObject* renderer) - : AccessibilityRenderObject(renderer) -{ -} - -AccessibilityList::~AccessibilityList() -{ -} - -PassRefPtr<AccessibilityList> AccessibilityList::create(RenderObject* renderer) -{ - return adoptRef(new AccessibilityList(renderer)); -} - -bool AccessibilityList::accessibilityIsIgnored() const -{ - // lists don't appear on tiger/leopard on the mac -#if PLATFORM(MAC) && (defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)) - return true; -#else - return false; -#endif -} - -bool AccessibilityList::isUnorderedList() const -{ - if (!m_renderer) - return false; - - Node* element = m_renderer->element(); - return element && element->hasTagName(ulTag); -} - -bool AccessibilityList::isOrderedList() const -{ - if (!m_renderer) - return false; - - Node* element = m_renderer->element(); - return element && element->hasTagName(olTag); -} - -bool AccessibilityList::isDefinitionList() const -{ - if (!m_renderer) - return false; - - Node* element = m_renderer->element(); - return element && element->hasTagName(dlTag); -} - - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityList.h b/src/3rdparty/webkit/WebCore/page/AccessibilityList.h deleted file mode 100644 index 315ccac..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityList.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2008 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 AccessibilityList_h -#define AccessibilityList_h - -#include "AccessibilityRenderObject.h" - -namespace WebCore { - -class AccessibilityList : public AccessibilityRenderObject { - -private: - AccessibilityList(RenderObject*); -public: - static PassRefPtr<AccessibilityList> create(RenderObject*); - virtual ~AccessibilityList(); - - virtual bool isList() const { return true; }; - bool isUnorderedList() const; - bool isOrderedList() const; - bool isDefinitionList() const; - - virtual AccessibilityRole roleValue() const { return ListRole; } - virtual bool accessibilityIsIgnored() const; - -}; - -} // namespace WebCore - -#endif // AccessibilityList_h diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityListBox.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityListBox.cpp deleted file mode 100644 index b94ccef..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityListBox.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AccessibilityListBox.h" - -#include "AXObjectCache.h" -#include "AccessibilityListBoxOption.h" -#include "HitTestResult.h" -#include "HTMLNames.h" -#include "HTMLSelectElement.h" -#include "RenderListBox.h" -#include "RenderObject.h" - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityListBox::AccessibilityListBox(RenderObject* renderer) - : AccessibilityRenderObject(renderer) -{ -} - -AccessibilityListBox::~AccessibilityListBox() -{ -} - -PassRefPtr<AccessibilityListBox> AccessibilityListBox::create(RenderObject* renderer) -{ - return adoptRef(new AccessibilityListBox(renderer)); -} - -bool AccessibilityListBox::canSetSelectedChildrenAttribute() const -{ - Node* selectNode = m_renderer->node(); - if (!selectNode) - return false; - - return !static_cast<HTMLSelectElement*>(selectNode)->disabled(); -} - -void AccessibilityListBox::addChildren() -{ - Node* selectNode = m_renderer->node(); - if (!selectNode) - return; - - m_haveChildren = true; - - const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(selectNode)->listItems(); - unsigned length = listItems.size(); - for (unsigned i = 0; i < length; i++) { - AccessibilityObject* listOption = listBoxOptionAccessibilityObject(listItems[i]); - if (listOption) - m_children.append(listOption); - } -} - -void AccessibilityListBox::setSelectedChildren(AccessibilityChildrenVector& children) -{ - if (!canSetSelectedChildrenAttribute()) - return; - - Node* selectNode = m_renderer->node(); - if (!selectNode) - return; - - // disable any selected options - unsigned length = m_children.size(); - for (unsigned i = 0; i < length; i++) { - AccessibilityListBoxOption* listBoxOption = static_cast<AccessibilityListBoxOption*>(m_children[i].get()); - if (listBoxOption->isSelected()) - listBoxOption->setSelected(false); - } - - length = children.size(); - for (unsigned i = 0; i < length; i++) { - AccessibilityObject* obj = children[i].get(); - if (obj->roleValue() != ListBoxOptionRole) - continue; - - static_cast<AccessibilityListBoxOption*>(obj)->setSelected(true); - } -} - -void AccessibilityListBox::selectedChildren(AccessibilityChildrenVector& result) -{ - ASSERT(result.isEmpty()); - - if (!hasChildren()) - addChildren(); - - unsigned length = m_children.size(); - for (unsigned i = 0; i < length; i++) { - if (static_cast<AccessibilityListBoxOption*>(m_children[i].get())->isSelected()) - result.append(m_children[i]); - } -} - -void AccessibilityListBox::visibleChildren(AccessibilityChildrenVector& result) -{ - ASSERT(result.isEmpty()); - - if (!hasChildren()) - addChildren(); - - unsigned length = m_children.size(); - for (unsigned i = 0; i < length; i++) { - if (static_cast<RenderListBox*>(m_renderer)->listIndexIsVisible(i)) - result.append(m_children[i]); - } -} - -AccessibilityObject* AccessibilityListBox::listBoxOptionAccessibilityObject(HTMLElement* element) const -{ - // skip hr elements - if (!element || element->hasTagName(hrTag)) - return 0; - - AccessibilityObject* listBoxObject = m_renderer->document()->axObjectCache()->get(ListBoxOptionRole); - static_cast<AccessibilityListBoxOption*>(listBoxObject)->setHTMLElement(element); - - return listBoxObject; -} - -AccessibilityObject* AccessibilityListBox::doAccessibilityHitTest(const IntPoint& point) const -{ - // the internal HTMLSelectElement methods for returning a listbox option at a point - // ignore optgroup elements. - if (!m_renderer) - return 0; - - Node* element = m_renderer->element(); - if (!element) - return 0; - - IntRect parentRect = boundingBoxRect(); - - const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(element)->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); - if (rect.contains(point)) - return listBoxOptionAccessibilityObject(listItems[i]); - } - - return axObjectCache()->get(m_renderer); -} - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityListBox.h b/src/3rdparty/webkit/WebCore/page/AccessibilityListBox.h deleted file mode 100644 index 3f3352d..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityListBox.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2008 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 AccessibilityListBox_h -#define AccessibilityListBox_h - -#include "AccessibilityObject.h" -#include "AccessibilityRenderObject.h" - -namespace WebCore { - -class AccessibilityListBox : public AccessibilityRenderObject { - -private: - AccessibilityListBox(RenderObject*); -public: - static PassRefPtr<AccessibilityListBox> create(RenderObject*); - virtual ~AccessibilityListBox(); - - virtual AccessibilityObject* doAccessibilityHitTest(const IntPoint&) const; - virtual bool isListBox() const { return true; }; - - virtual bool canSetFocusAttribute() const { return true; } - virtual bool canSetSelectedChildrenAttribute() const; - void setSelectedChildren(AccessibilityChildrenVector&); - virtual AccessibilityRole roleValue() const { return ListBoxRole; } - - virtual bool accessibilityIsIgnored() const { return false; } - - virtual void selectedChildren(AccessibilityChildrenVector&); - virtual void visibleChildren(AccessibilityChildrenVector&); - - virtual void addChildren(); - -private: - AccessibilityObject* listBoxOptionAccessibilityObject(HTMLElement*) const; -}; - -} // namespace WebCore - -#endif // AccessibilityListBox_h diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityListBoxOption.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityListBoxOption.cpp deleted file mode 100644 index fedfe91..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityListBoxOption.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AccessibilityListBoxOption.h" - -#include "AXObjectCache.h" -#include "AccessibilityListBox.h" -#include "Element.h" -#include "HTMLElement.h" -#include "HTMLNames.h" -#include "HTMLOptionElement.h" -#include "HTMLOptGroupElement.h" -#include "HTMLSelectElement.h" -#include "IntRect.h" -#include "RenderObject.h" -#include "RenderListBox.h" - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityListBoxOption::AccessibilityListBoxOption() - : m_optionElement(0) -{ -} - -AccessibilityListBoxOption::~AccessibilityListBoxOption() -{ -} - -PassRefPtr<AccessibilityListBoxOption> AccessibilityListBoxOption::create() -{ - return adoptRef(new AccessibilityListBoxOption()); -} - -bool AccessibilityListBoxOption::isEnabled() const -{ - if (!m_optionElement) - return false; - - if (m_optionElement->hasTagName(optgroupTag)) - return false; - - return true; -} - -bool AccessibilityListBoxOption::isSelected() const -{ - if (!m_optionElement) - return false; - - if (!m_optionElement->hasTagName(optionTag)) - return false; - - return static_cast<HTMLOptionElement*>(m_optionElement)->selected(); -} - -IntRect AccessibilityListBoxOption::elementRect() const -{ - IntRect rect; - if (!m_optionElement) - return rect; - - HTMLSelectElement* listBoxParentNode = listBoxOptionParentNode(); - if (!listBoxParentNode) - return rect; - - RenderObject* listBoxRenderer = listBoxParentNode->renderer(); - if (!listBoxRenderer) - return rect; - - IntRect parentRect = listBoxRenderer->document()->axObjectCache()->get(listBoxRenderer)->boundingBoxRect(); - int index = listBoxOptionIndex(); - if (index != -1) - rect = static_cast<RenderListBox*>(listBoxRenderer)->itemBoundingBoxRect(parentRect.x(), parentRect.y(), index); - - return rect; -} - -bool AccessibilityListBoxOption::canSetSelectedAttribute() const -{ - if (!m_optionElement) - return false; - - if (!m_optionElement->hasTagName(optionTag)) - return false; - - if (m_optionElement->disabled()) - return false; - - HTMLSelectElement* selectElement = listBoxOptionParentNode(); - if (selectElement && selectElement->disabled()) - return false; - - return true; -} - -String AccessibilityListBoxOption::stringValue() const -{ - if (!m_optionElement) - return String(); - - if (m_optionElement->hasTagName(optionTag)) - return static_cast<HTMLOptionElement*>(m_optionElement)->text(); - - if (m_optionElement->hasTagName(optgroupTag)) - return static_cast<HTMLOptGroupElement*>(m_optionElement)->groupLabelText(); - - return String(); -} - -IntSize AccessibilityListBoxOption::size() const -{ - return elementRect().size(); -} - -Element* AccessibilityListBoxOption::actionElement() const -{ - return m_optionElement; -} - -AccessibilityObject* AccessibilityListBoxOption::parentObject() const -{ - HTMLSelectElement* parentNode = listBoxOptionParentNode(); - if (!parentNode) - return 0; - - return m_optionElement->document()->axObjectCache()->get(parentNode->renderer()); -} - -void AccessibilityListBoxOption::setSelected(bool selected) -{ - HTMLSelectElement* selectElement = listBoxOptionParentNode(); - if (!selectElement) - return; - - if (!canSetSelectedAttribute()) - return; - - bool isOptionSelected = isSelected(); - if ((isOptionSelected && selected) || (!isOptionSelected && !selected)) - return; - - selectElement->accessKeySetSelectedIndex(listBoxOptionIndex()); -} - -HTMLSelectElement* AccessibilityListBoxOption::listBoxOptionParentNode() const -{ - if (!m_optionElement) - return 0; - - if (m_optionElement->hasTagName(optionTag)) - return static_cast<HTMLOptionElement*>(m_optionElement)->ownerSelectElement(); - - if (m_optionElement->hasTagName(optgroupTag)) - return static_cast<HTMLOptGroupElement*>(m_optionElement)->ownerSelectElement(); - - return 0; -} - -int AccessibilityListBoxOption::listBoxOptionIndex() const -{ - if (!m_optionElement) - return -1; - - HTMLSelectElement* selectElement = listBoxOptionParentNode(); - if (!selectElement) - return -1; - - const Vector<HTMLElement*>& listItems = selectElement->listItems(); - unsigned length = listItems.size(); - for (unsigned i = 0; i < length; i++) - if (listItems[i] == m_optionElement) - return i; - - return -1; -} - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityListBoxOption.h b/src/3rdparty/webkit/WebCore/page/AccessibilityListBoxOption.h deleted file mode 100644 index 1b588cd..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityListBoxOption.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2008 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 AccessibilityListBoxOption_h -#define AccessibilityListBoxOption_h - -#include "AccessibilityObject.h" -#include "HTMLElement.h" - -namespace WebCore { - -class AccessibilityListBox; -class Element; -class HTMLElement; -class HTMLSelectElement; -class String; - -class AccessibilityListBoxOption : public AccessibilityObject { - -private: - AccessibilityListBoxOption(); -public: - static PassRefPtr<AccessibilityListBoxOption> create(); - virtual ~AccessibilityListBoxOption(); - - void setHTMLElement(HTMLElement* element) { m_optionElement = element; } - - virtual AccessibilityRole roleValue() const { return ListBoxOptionRole; } - virtual bool accessibilityIsIgnored() const { return false; } - virtual bool isSelected() const; - virtual bool isEnabled() const; - virtual String stringValue() const; - virtual Element* actionElement() const; - - virtual void setSelected(bool); - virtual bool canSetSelectedAttribute() const; - - virtual IntRect elementRect() const; - virtual IntSize size() const; - virtual AccessibilityObject* parentObject() const; - bool isListBoxOption() const { return true; }; - -private: - HTMLElement* m_optionElement; - - HTMLSelectElement* listBoxOptionParentNode() const; - int listBoxOptionIndex() const; - IntRect listBoxOptionRect() const; - AccessibilityObject* listBoxOptionAccessibilityObject(HTMLElement* element) const; -}; - -} // namespace WebCore - -#endif // AccessibilityListBoxOption_h diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityObject.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityObject.cpp deleted file mode 100644 index 0b072cf..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityObject.cpp +++ /dev/null @@ -1,1031 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AccessibilityObject.h" - -#include "AccessibilityRenderObject.h" -#include "AXObjectCache.h" -#include "CharacterNames.h" -#include "FloatRect.h" -#include "FocusController.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "LocalizedStrings.h" -#include "NodeList.h" -#include "NotImplemented.h" -#include "Page.h" -#include "RenderImage.h" -#include "RenderListMarker.h" -#include "RenderMenuList.h" -#include "RenderTextControl.h" -#include "RenderTheme.h" -#include "RenderView.h" -#include "RenderWidget.h" -#include "SelectionController.h" -#include "TextIterator.h" -#include "htmlediting.h" -#include "visible_units.h" -#include <wtf/StdLibExtras.h> - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityObject::AccessibilityObject() - : m_id(0) - , m_haveChildren(false) -#if PLATFORM(GTK) - , m_wrapper(0) -#endif -{ -} - -AccessibilityObject::~AccessibilityObject() -{ - ASSERT(isDetached()); -} - -void AccessibilityObject::detach() -{ - removeAXObjectID(); -#if HAVE(ACCESSIBILITY) - setWrapper(0); -#endif -} - -AccessibilityObject* AccessibilityObject::firstChild() const -{ - return 0; -} - -AccessibilityObject* AccessibilityObject::lastChild() const -{ - return 0; -} - -AccessibilityObject* AccessibilityObject::previousSibling() const -{ - return 0; -} - -AccessibilityObject* AccessibilityObject::nextSibling() const -{ - return 0; -} - -AccessibilityObject* AccessibilityObject::parentObject() const -{ - return 0; -} - -AccessibilityObject* AccessibilityObject::parentObjectUnignored() const -{ - AccessibilityObject* parent; - for (parent = parentObject(); parent && parent->accessibilityIsIgnored(); parent = parent->parentObject()) - ; - return parent; -} - -int AccessibilityObject::layoutCount() const -{ - return 0; -} - -String AccessibilityObject::text() const -{ - return String(); -} - -String AccessibilityObject::helpText() const -{ - return String(); -} - -String AccessibilityObject::textUnderElement() const -{ - return String(); -} - -bool AccessibilityObject::isARIAInput(AccessibilityRole ariaRole) -{ - return ariaRole == RadioButtonRole || ariaRole == CheckBoxRole || ariaRole == TextFieldRole; -} - -bool AccessibilityObject::isARIAControl(AccessibilityRole ariaRole) -{ - return isARIAInput(ariaRole) || ariaRole == TextAreaRole || ariaRole == ButtonRole - || ariaRole == ComboBoxRole || ariaRole == SliderRole; -} - -int AccessibilityObject::intValue() const -{ - return 0; -} - -String AccessibilityObject::stringValue() const -{ - return String(); -} - -String AccessibilityObject::ariaAccessiblityName(const String&) const -{ - return String(); -} - -String AccessibilityObject::ariaLabeledByAttribute() const -{ - return String(); -} - -String AccessibilityObject::title() const -{ - return String(); -} - -String AccessibilityObject::ariaDescribedByAttribute() const -{ - return String(); -} - -String AccessibilityObject::accessibilityDescription() const -{ - return String(); -} - -IntRect AccessibilityObject::boundingBoxRect() const -{ - return IntRect(); -} - -IntRect AccessibilityObject::elementRect() const -{ - return IntRect(); -} - -IntSize AccessibilityObject::size() const -{ - return IntSize(); -} - -IntPoint AccessibilityObject::clickPoint() const -{ - IntRect rect = elementRect(); - return IntPoint(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2); -} - -void AccessibilityObject::linkedUIElements(AccessibilityChildrenVector&) const -{ - return; -} - -AccessibilityObject* AccessibilityObject::titleUIElement() const -{ - return 0; -} - -int AccessibilityObject::textLength() const -{ - return 0; -} - -PassRefPtr<Range> AccessibilityObject::ariaSelectedTextDOMRange() const -{ - return 0; -} - -String AccessibilityObject::selectedText() const -{ - return String(); -} - -const AtomicString& AccessibilityObject::accessKey() const -{ - return nullAtom; -} - -Selection AccessibilityObject::selection() const -{ - return Selection(); -} - -PlainTextRange AccessibilityObject::selectedTextRange() const -{ - return PlainTextRange(); -} - -unsigned AccessibilityObject::selectionStart() const -{ - return selectedTextRange().start; -} - -unsigned AccessibilityObject::selectionEnd() const -{ - return selectedTextRange().length; -} - -void AccessibilityObject::setSelectedText(const String&) -{ - // TODO: set selected text (ReplaceSelectionCommand). <rdar://problem/4712125> - notImplemented(); -} - -void AccessibilityObject::setSelectedTextRange(const PlainTextRange&) -{ -} - -void AccessibilityObject::makeRangeVisible(const PlainTextRange&) -{ - // TODO: make range visible (scrollRectToVisible). <rdar://problem/4712101> - notImplemented(); -} - -KURL AccessibilityObject::url() const -{ - return KURL(); -} - -void AccessibilityObject::setFocused(bool) -{ -} - -void AccessibilityObject::setValue(const String&) -{ -} - -void AccessibilityObject::setSelected(bool) -{ -} - -bool AccessibilityObject::press() const -{ - Element* actionElem = actionElement(); - if (!actionElem) - return false; - if (Frame* f = actionElem->document()->frame()) - f->loader()->resetMultipleFormSubmissionProtection(); - actionElem->accessKeyAction(true); - return true; -} - -AXObjectCache* AccessibilityObject::axObjectCache() const -{ - return 0; -} - -Widget* AccessibilityObject::widget() const -{ - return 0; -} - -Widget* AccessibilityObject::widgetForAttachmentView() const -{ - return 0; -} - -Element* AccessibilityObject::anchorElement() const -{ - return 0; -} - -Element* AccessibilityObject::actionElement() const -{ - return 0; -} - -// This function is like a cross-platform version of - (WebCoreTextMarkerRange*)textMarkerRange. It returns -// a Range that we can convert to a WebCoreRange in the Obj-C file -VisiblePositionRange AccessibilityObject::visiblePositionRange() const -{ - return VisiblePositionRange(); -} - -VisiblePositionRange AccessibilityObject::visiblePositionRangeForLine(unsigned) const -{ - return VisiblePositionRange(); -} - -VisiblePosition AccessibilityObject::visiblePositionForIndex(int) const -{ - return VisiblePosition(); -} - -int AccessibilityObject::indexForVisiblePosition(const VisiblePosition&) const -{ - return 0; -} - -VisiblePositionRange AccessibilityObject::visiblePositionRangeForUnorderedPositions(const VisiblePosition& visiblePos1, const VisiblePosition& visiblePos2) const -{ - if (visiblePos1.isNull() || visiblePos2.isNull()) - return VisiblePositionRange(); - - VisiblePosition startPos; - VisiblePosition endPos; - bool alreadyInOrder; - - // upstream is ordered before downstream for the same position - if (visiblePos1 == visiblePos2 && visiblePos2.affinity() == UPSTREAM) - alreadyInOrder = false; - - // use selection order to see if the positions are in order - else - alreadyInOrder = Selection(visiblePos1, visiblePos2).isBaseFirst(); - - if (alreadyInOrder) { - startPos = visiblePos1; - endPos = visiblePos2; - } else { - startPos = visiblePos2; - endPos = visiblePos1; - } - - return VisiblePositionRange(startPos, endPos); -} - -VisiblePositionRange AccessibilityObject::positionOfLeftWord(const VisiblePosition& visiblePos) const -{ - VisiblePosition startPosition = startOfWord(visiblePos, LeftWordIfOnBoundary); - VisiblePosition endPosition = endOfWord(startPosition); - return VisiblePositionRange(startPosition, endPosition); -} - -VisiblePositionRange AccessibilityObject::positionOfRightWord(const VisiblePosition& visiblePos) const -{ - VisiblePosition startPosition = startOfWord(visiblePos, RightWordIfOnBoundary); - VisiblePosition endPosition = endOfWord(startPosition); - return VisiblePositionRange(startPosition, endPosition); -} - -static VisiblePosition updateAXLineStartForVisiblePosition(const VisiblePosition& visiblePosition) -{ - // A line in the accessibility sense should include floating objects, such as aligned image, as part of a line. - // So let's update the position to include that. - VisiblePosition tempPosition; - VisiblePosition startPosition = visiblePosition; - Position p; - RenderObject* renderer; - while (true) { - tempPosition = startPosition.previous(); - if (tempPosition.isNull()) - break; - p = tempPosition.deepEquivalent(); - if (!p.node()) - break; - renderer = p.node()->renderer(); - if (!renderer || renderer->isRenderBlock() && !p.offset()) - break; - InlineBox* box; - int ignoredCaretOffset; - p.getInlineBoxAndOffset(tempPosition.affinity(), box, ignoredCaretOffset); - if (box) - break; - startPosition = tempPosition; - } - - return startPosition; -} - -VisiblePositionRange AccessibilityObject::leftLineVisiblePositionRange(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return VisiblePositionRange(); - - // make a caret selection for the position before marker position (to make sure - // we move off of a line start) - VisiblePosition prevVisiblePos = visiblePos.previous(); - if (prevVisiblePos.isNull()) - return VisiblePositionRange(); - - VisiblePosition startPosition = startOfLine(prevVisiblePos); - - // keep searching for a valid line start position. Unless the VisiblePosition is at the very beginning, there should - // always be a valid line range. However, startOfLine will return null for position next to a floating object, - // since floating object doesn't really belong to any line. - // This check will reposition the marker before the floating object, to ensure we get a line start. - if (startPosition.isNull()) { - while (startPosition.isNull() && prevVisiblePos.isNotNull()) { - prevVisiblePos = prevVisiblePos.previous(); - startPosition = startOfLine(prevVisiblePos); - } - } else - startPosition = updateAXLineStartForVisiblePosition(startPosition); - - VisiblePosition endPosition = endOfLine(prevVisiblePos); - return VisiblePositionRange(startPosition, endPosition); -} - -VisiblePositionRange AccessibilityObject::rightLineVisiblePositionRange(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return VisiblePositionRange(); - - // make sure we move off of a line end - VisiblePosition nextVisiblePos = visiblePos.next(); - if (nextVisiblePos.isNull()) - return VisiblePositionRange(); - - VisiblePosition startPosition = startOfLine(nextVisiblePos); - - // fetch for a valid line start position - if (startPosition.isNull() ) { - startPosition = visiblePos; - nextVisiblePos = nextVisiblePos.next(); - } else - startPosition = updateAXLineStartForVisiblePosition(startPosition); - - VisiblePosition endPosition = endOfLine(nextVisiblePos); - - // as long as the position hasn't reached the end of the doc, keep searching for a valid line end position - // Unless the VisiblePosition is at the very end, there should always be a valid line range. However, endOfLine will - // return null for position by a floating object, since floating object doesn't really belong to any line. - // This check will reposition the marker after the floating object, to ensure we get a line end. - while (endPosition.isNull() && nextVisiblePos.isNotNull()) { - nextVisiblePos = nextVisiblePos.next(); - endPosition = endOfLine(nextVisiblePos); - } - - return VisiblePositionRange(startPosition, endPosition); -} - -VisiblePositionRange AccessibilityObject::sentenceForPosition(const VisiblePosition& visiblePos) const -{ - // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer) - // Related? <rdar://problem/3927736> Text selection broken in 8A336 - VisiblePosition startPosition = startOfSentence(visiblePos); - VisiblePosition endPosition = endOfSentence(startPosition); - return VisiblePositionRange(startPosition, endPosition); -} - -VisiblePositionRange AccessibilityObject::paragraphForPosition(const VisiblePosition& visiblePos) const -{ - VisiblePosition startPosition = startOfParagraph(visiblePos); - VisiblePosition endPosition = endOfParagraph(startPosition); - return VisiblePositionRange(startPosition, endPosition); -} - -static VisiblePosition startOfStyleRange(const VisiblePosition visiblePos) -{ - RenderObject* renderer = visiblePos.deepEquivalent().node()->renderer(); - RenderObject* startRenderer = renderer; - RenderStyle* style = renderer->style(); - - // traverse backward by renderer to look for style change - for (RenderObject* r = renderer->previousInPreOrder(); r; r = r->previousInPreOrder()) { - // skip non-leaf nodes - if (r->firstChild()) - continue; - - // stop at style change - if (r->style() != style) - break; - - // remember match - startRenderer = r; - } - - return VisiblePosition(startRenderer->node(), 0, VP_DEFAULT_AFFINITY); -} - -static VisiblePosition endOfStyleRange(const VisiblePosition visiblePos) -{ - RenderObject* renderer = visiblePos.deepEquivalent().node()->renderer(); - RenderObject* endRenderer = renderer; - RenderStyle* style = renderer->style(); - - // traverse forward by renderer to look for style change - for (RenderObject* r = renderer->nextInPreOrder(); r; r = r->nextInPreOrder()) { - // skip non-leaf nodes - if (r->firstChild()) - continue; - - // stop at style change - if (r->style() != style) - break; - - // remember match - endRenderer = r; - } - - return VisiblePosition(endRenderer->node(), maxDeepOffset(endRenderer->node()), VP_DEFAULT_AFFINITY); -} - -VisiblePositionRange AccessibilityObject::styleRangeForPosition(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return VisiblePositionRange(); - - return VisiblePositionRange(startOfStyleRange(visiblePos), endOfStyleRange(visiblePos)); -} - -// NOTE: Consider providing this utility method as AX API -VisiblePositionRange AccessibilityObject::visiblePositionRangeForRange(const PlainTextRange& range) const -{ - if (range.start + range.length > text().length()) - return VisiblePositionRange(); - - VisiblePosition startPosition = visiblePositionForIndex(range.start); - startPosition.setAffinity(DOWNSTREAM); - VisiblePosition endPosition = visiblePositionForIndex(range.start + range.length); - return VisiblePositionRange(startPosition, endPosition); -} - -static bool replacedNodeNeedsCharacter(Node* replacedNode) -{ - // we should always be given a rendered node and a replaced node, but be safe - // replaced nodes are either attachments (widgets) or images - if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) { - return false; - } - - // create an AX object, but skip it if it is not supposed to be seen - AccessibilityObject* object = replacedNode->renderer()->document()->axObjectCache()->get(replacedNode->renderer()); - if (object->accessibilityIsIgnored()) - return false; - - return true; -} - -String AccessibilityObject::stringForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const -{ - if (visiblePositionRange.isNull()) - return String(); - - Vector<UChar> resultVector; - RefPtr<Range> range = makeRange(visiblePositionRange.start, visiblePositionRange.end); - for (TextIterator it(range.get()); !it.atEnd(); it.advance()) { - // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX) - if (it.length() != 0) { - resultVector.append(it.characters(), it.length()); - } else { - // locate the node and starting offset for this replaced range - int exception = 0; - Node* node = it.range()->startContainer(exception); - ASSERT(node == it.range()->endContainer(exception)); - int offset = it.range()->startOffset(exception); - - if (replacedNodeNeedsCharacter(node->childNode(offset))) { - resultVector.append(objectReplacementCharacter); - } - } - } - - return String::adopt(resultVector); -} - -IntRect AccessibilityObject::boundsForVisiblePositionRange(const VisiblePositionRange&) const -{ - return IntRect(); -} - -int AccessibilityObject::lengthForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const -{ - // FIXME: Multi-byte support - if (visiblePositionRange.isNull()) - return -1; - - int length = 0; - RefPtr<Range> range = makeRange(visiblePositionRange.start, visiblePositionRange.end); - for (TextIterator it(range.get()); !it.atEnd(); it.advance()) { - // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX) - if (it.length() != 0) { - length += it.length(); - } else { - // locate the node and starting offset for this replaced range - int exception = 0; - Node* node = it.range()->startContainer(exception); - ASSERT(node == it.range()->endContainer(exception)); - int offset = it.range()->startOffset(exception); - - if (replacedNodeNeedsCharacter(node->childNode(offset))) - length++; - } - } - - return length; -} - -void AccessibilityObject::setSelectedVisiblePositionRange(const VisiblePositionRange&) const -{ -} - -VisiblePosition AccessibilityObject::visiblePositionForPoint(const IntPoint&) const -{ - return VisiblePosition(); -} - -VisiblePosition AccessibilityObject::nextVisiblePosition(const VisiblePosition& visiblePos) const -{ - return visiblePos.next(); -} - -VisiblePosition AccessibilityObject::previousVisiblePosition(const VisiblePosition& visiblePos) const -{ - return visiblePos.previous(); -} - -VisiblePosition AccessibilityObject::nextWordEnd(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return VisiblePosition(); - - // make sure we move off of a word end - VisiblePosition nextVisiblePos = visiblePos.next(); - if (nextVisiblePos.isNull()) - return VisiblePosition(); - - return endOfWord(nextVisiblePos, LeftWordIfOnBoundary); -} - -VisiblePosition AccessibilityObject::previousWordStart(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return VisiblePosition(); - - // make sure we move off of a word start - VisiblePosition prevVisiblePos = visiblePos.previous(); - if (prevVisiblePos.isNull()) - return VisiblePosition(); - - return startOfWord(prevVisiblePos, RightWordIfOnBoundary); -} - -VisiblePosition AccessibilityObject::nextLineEndPosition(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return VisiblePosition(); - - // to make sure we move off of a line end - VisiblePosition nextVisiblePos = visiblePos.next(); - if (nextVisiblePos.isNull()) - return VisiblePosition(); - - VisiblePosition endPosition = endOfLine(nextVisiblePos); - - // as long as the position hasn't reached the end of the doc, keep searching for a valid line end position - // There are cases like when the position is next to a floating object that'll return null for end of line. This code will avoid returning null. - while (endPosition.isNull() && nextVisiblePos.isNotNull()) { - nextVisiblePos = nextVisiblePos.next(); - endPosition = endOfLine(nextVisiblePos); - } - - return endPosition; -} - -VisiblePosition AccessibilityObject::previousLineStartPosition(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return VisiblePosition(); - - // make sure we move off of a line start - VisiblePosition prevVisiblePos = visiblePos.previous(); - if (prevVisiblePos.isNull()) - return VisiblePosition(); - - VisiblePosition startPosition = startOfLine(prevVisiblePos); - - // as long as the position hasn't reached the beginning of the doc, keep searching for a valid line start position - // There are cases like when the position is next to a floating object that'll return null for start of line. This code will avoid returning null. - if (startPosition.isNull()) { - while (startPosition.isNull() && prevVisiblePos.isNotNull()) { - prevVisiblePos = prevVisiblePos.previous(); - startPosition = startOfLine(prevVisiblePos); - } - } else - startPosition = updateAXLineStartForVisiblePosition(startPosition); - - return startPosition; -} - -VisiblePosition AccessibilityObject::nextSentenceEndPosition(const VisiblePosition& visiblePos) const -{ - // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer) - // Related? <rdar://problem/3927736> Text selection broken in 8A336 - if (visiblePos.isNull()) - return VisiblePosition(); - - // make sure we move off of a sentence end - VisiblePosition nextVisiblePos = visiblePos.next(); - if (nextVisiblePos.isNull()) - return VisiblePosition(); - - // an empty line is considered a sentence. If it's skipped, then the sentence parser will not - // see this empty line. Instead, return the end position of the empty line. - VisiblePosition endPosition; - String lineString = plainText(makeRange(startOfLine(visiblePos), endOfLine(visiblePos)).get()); - if (lineString.isEmpty()) - endPosition = nextVisiblePos; - else - endPosition = endOfSentence(nextVisiblePos); - - return endPosition; -} - -VisiblePosition AccessibilityObject::previousSentenceStartPosition(const VisiblePosition& visiblePos) const -{ - // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer) - // Related? <rdar://problem/3927736> Text selection broken in 8A336 - if (visiblePos.isNull()) - return VisiblePosition(); - - // make sure we move off of a sentence start - VisiblePosition previousVisiblePos = visiblePos.previous(); - if (previousVisiblePos.isNull()) - return VisiblePosition(); - - // treat empty line as a separate sentence. - VisiblePosition startPosition; - String lineString = plainText(makeRange(startOfLine(previousVisiblePos), endOfLine(previousVisiblePos)).get()); - if (lineString.isEmpty()) - startPosition = previousVisiblePos; - else - startPosition = startOfSentence(previousVisiblePos); - - return startPosition; -} - -VisiblePosition AccessibilityObject::nextParagraphEndPosition(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return VisiblePosition(); - - // make sure we move off of a paragraph end - VisiblePosition nextPos = visiblePos.next(); - if (nextPos.isNull()) - return VisiblePosition(); - - return endOfParagraph(nextPos); -} - -VisiblePosition AccessibilityObject::previousParagraphStartPosition(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return VisiblePosition(); - - // make sure we move off of a paragraph start - VisiblePosition previousPos = visiblePos.previous(); - if (previousPos.isNull()) - return VisiblePosition(); - - return startOfParagraph(previousPos); -} - -// NOTE: Consider providing this utility method as AX API -VisiblePosition AccessibilityObject::visiblePositionForIndex(unsigned, bool) const -{ - return VisiblePosition(); -} - -AccessibilityObject* AccessibilityObject::accessibilityObjectForPosition(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return 0; - - RenderObject* obj = visiblePos.deepEquivalent().node()->renderer(); - if (!obj) - return 0; - - return obj->document()->axObjectCache()->get(obj); -} - -int AccessibilityObject::lineForPosition(const VisiblePosition& visiblePos) const -{ - if (visiblePos.isNull()) - return 0; - - unsigned lineCount = 0; - VisiblePosition currentVisiblePos = visiblePos; - VisiblePosition savedVisiblePos; - - // move up until we get to the top - // FIXME: This only takes us to the top of the rootEditableElement, not the top of the - // top document. - while (currentVisiblePos.isNotNull() && !(inSameLine(currentVisiblePos, savedVisiblePos))) { - ++lineCount; - savedVisiblePos = currentVisiblePos; - VisiblePosition prevVisiblePos = previousLinePosition(currentVisiblePos, 0); - currentVisiblePos = prevVisiblePos; - } - - return lineCount - 1; -} - -// NOTE: Consider providing this utility method as AX API -PlainTextRange AccessibilityObject::plainTextRangeForVisiblePositionRange(const VisiblePositionRange& positionRange) const -{ - int index1 = index(positionRange.start); - int index2 = index(positionRange.end); - if (index1 < 0 || index2 < 0 || index1 > index2) - return PlainTextRange(); - - return PlainTextRange(index1, index2 - index1); -} - -// NOTE: Consider providing this utility method as AX API -int AccessibilityObject::index(const VisiblePosition&) const -{ - return -1; -} - -// Given a line number, the range of characters of the text associated with this accessibility -// object that contains the line number. -PlainTextRange AccessibilityObject::doAXRangeForLine(unsigned) const -{ - return PlainTextRange(); -} - -// The composed character range in the text associated with this accessibility object that -// is specified by the given screen coordinates. This parameterized attribute returns the -// complete range of characters (including surrogate pairs of multi-byte glyphs) at the given -// screen coordinates. -// NOTE: This varies from AppKit when the point is below the last line. AppKit returns an -// an error in that case. We return textControl->text().length(), 1. Does this matter? -PlainTextRange AccessibilityObject::doAXRangeForPosition(const IntPoint& point) const -{ - int i = index(visiblePositionForPoint(point)); - if (i < 0) - return PlainTextRange(); - - return PlainTextRange(i, 1); -} - -// The composed character range in the text associated with this accessibility object that -// is specified by the given index value. This parameterized attribute returns the complete -// range of characters (including surrogate pairs of multi-byte glyphs) at the given index. -PlainTextRange AccessibilityObject::doAXRangeForIndex(unsigned) const -{ - return PlainTextRange(); -} - -// Given a character index, the range of text associated with this accessibility object -// over which the style in effect at that character index applies. -PlainTextRange AccessibilityObject::doAXStyleRangeForIndex(unsigned index) const -{ - VisiblePositionRange range = styleRangeForPosition(visiblePositionForIndex(index, false)); - return plainTextRangeForVisiblePositionRange(range); -} - -// A substring of the text associated with this accessibility object that is -// specified by the given character range. -String AccessibilityObject::doAXStringForRange(const PlainTextRange&) const -{ - return String(); -} - -// The bounding rectangle of the text associated with this accessibility object that is -// specified by the given range. This is the bounding rectangle a sighted user would see -// on the display screen, in pixels. -IntRect AccessibilityObject::doAXBoundsForRange(const PlainTextRange&) const -{ - return IntRect(); -} - -// Given an indexed character, the line number of the text associated with this accessibility -// object that contains the character. -unsigned AccessibilityObject::doAXLineForIndex(unsigned index) -{ - return lineForPosition(visiblePositionForIndex(index, false)); -} - -FrameView* AccessibilityObject::documentFrameView() const -{ - const AccessibilityObject* object = this; - while (object && !object->isAccessibilityRenderObject()) - object = object->parentObject(); - - if (!object) - return 0; - - return object->documentFrameView(); -} - -AccessibilityObject* AccessibilityObject::doAccessibilityHitTest(const IntPoint&) const -{ - return 0; -} - -AccessibilityObject* AccessibilityObject::focusedUIElement() const -{ - return 0; -} - -AccessibilityObject* AccessibilityObject::observableObject() const -{ - return 0; -} - -AccessibilityRole AccessibilityObject::roleValue() const -{ - return UnknownRole; -} - -AccessibilityRole AccessibilityObject::ariaRoleAttribute() const -{ - return UnknownRole; -} - -bool AccessibilityObject::isPresentationalChildOfAriaRole() const -{ - return false; -} - -bool AccessibilityObject::ariaRoleHasPresentationalChildren() const -{ - return false; -} - -void AccessibilityObject::clearChildren() -{ - m_haveChildren = false; - m_children.clear(); -} - -void AccessibilityObject::childrenChanged() -{ - return; -} - -void AccessibilityObject::addChildren() -{ -} - -void AccessibilityObject::selectedChildren(AccessibilityChildrenVector&) -{ -} - -void AccessibilityObject::visibleChildren(AccessibilityChildrenVector&) -{ -} - -unsigned AccessibilityObject::axObjectID() const -{ - return m_id; -} - -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. - DEFINE_STATIC_LOCAL(const String, buttonAction, (AXButtonActionVerb())); - DEFINE_STATIC_LOCAL(const String, textFieldAction, (AXTextFieldActionVerb())); - DEFINE_STATIC_LOCAL(const String, radioButtonAction, (AXRadioButtonActionVerb())); - DEFINE_STATIC_LOCAL(const String, checkedCheckBoxAction, (AXCheckedCheckBoxActionVerb())); - DEFINE_STATIC_LOCAL(const String, uncheckedCheckBoxAction, (AXUncheckedCheckBoxActionVerb())); - DEFINE_STATIC_LOCAL(const String, linkAction, (AXLinkActionVerb())); - DEFINE_STATIC_LOCAL(const String, noAction, ()); - - switch (roleValue()) { - case ButtonRole: - return buttonAction; - case TextFieldRole: - case TextAreaRole: - return textFieldAction; - case RadioButtonRole: - return radioButtonAction; - case CheckBoxRole: - return isChecked() ? checkedCheckBoxAction : uncheckedCheckBoxAction; - case LinkRole: - case WebCoreLinkRole: - return linkAction; - default: - return noAction; - } -} - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityObject.h b/src/3rdparty/webkit/WebCore/page/AccessibilityObject.h deleted file mode 100644 index e177ee7..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityObject.h +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * Copyright (C) 2008 Nuanti Ltd. - * - * 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 AccessibilityObject_h -#define AccessibilityObject_h - -#include "VisiblePosition.h" -#include <wtf/Platform.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> - -#if PLATFORM(MAC) -#include <wtf/RetainPtr.h> -#elif PLATFORM(WIN) -#include "AccessibilityObjectWrapperWin.h" -#include "COMPtr.h" -#elif PLATFORM(CHROMIUM) -#include "AccessibilityObjectWrapper.h" -#endif - -typedef struct _NSRange NSRange; - -#ifdef __OBJC__ -@class AccessibilityObjectWrapper; -@class NSArray; -@class NSAttributedString; -@class NSData; -@class NSMutableAttributedString; -@class NSString; -@class NSValue; -@class NSView; -#else -class NSArray; -class NSAttributedString; -class NSData; -class NSMutableAttributedString; -class NSString; -class NSValue; -class NSView; -#if PLATFORM(GTK) -typedef struct _AtkObject AtkObject; -typedef struct _AtkObject AccessibilityObjectWrapper; -#else -class AccessibilityObjectWrapper; -#endif -#endif - -namespace WebCore { - -class AXObjectCache; -class Element; -class Frame; -class FrameView; -class HTMLAnchorElement; -class HTMLAreaElement; -class IntPoint; -class IntSize; -class Node; -class RenderObject; -class Selection; -class String; -class Widget; - -enum AccessibilityRole { - UnknownRole = 1, - ButtonRole, - RadioButtonRole, - CheckBoxRole, - SliderRole, - TabGroupRole, - TextFieldRole, - StaticTextRole, - TextAreaRole, - ScrollAreaRole, - PopUpButtonRole, - MenuButtonRole, - TableRole, - ApplicationRole, - GroupRole, - RadioGroupRole, - ListRole, - ScrollBarRole, - ValueIndicatorRole, - ImageRole, - MenuBarRole, - MenuRole, - MenuItemRole, - ColumnRole, - RowRole, - ToolbarRole, - BusyIndicatorRole, - ProgressIndicatorRole, - WindowRole, - DrawerRole, - SystemWideRole, - OutlineRole, - IncrementorRole, - BrowserRole, - ComboBoxRole, - SplitGroupRole, - SplitterRole, - ColorWellRole, - GrowAreaRole, - SheetRole, - HelpTagRole, - MatteRole, - RulerRole, - RulerMarkerRole, - LinkRole, - DisclosureTriangleRole, - GridRole, - CellRole, - // AppKit includes SortButtonRole but it is misnamed and really a subrole of ButtonRole so we do not include it here. - - // WebCore-specific roles - WebCoreLinkRole, - ImageMapLinkRole, - ImageMapRole, - ListMarkerRole, - WebAreaRole, - HeadingRole, - ListBoxRole, - ListBoxOptionRole, - TableHeaderContainerRole, - DefinitionListTermRole, - DefinitionListDefinitionRole -}; - -struct VisiblePositionRange { - - VisiblePosition start; - VisiblePosition end; - - VisiblePositionRange() {} - - VisiblePositionRange(const VisiblePosition& s, const VisiblePosition& e) - : start(s) - , end(e) - { } - - bool isNull() const { return start.isNull() || end.isNull(); } -}; - -struct PlainTextRange { - - unsigned start; - unsigned length; - - PlainTextRange() - : start(0) - , length(0) - { } - - PlainTextRange(unsigned s, unsigned l) - : start(s) - , length(l) - { } - - bool isNull() const { return start == 0 && length == 0; } -}; - -class AccessibilityObject : public RefCounted<AccessibilityObject> { -protected: - AccessibilityObject(); -public: - virtual ~AccessibilityObject(); - - typedef Vector<RefPtr<AccessibilityObject> > AccessibilityChildrenVector; - - virtual bool isAccessibilityRenderObject() const { return false; }; - virtual bool isAnchor() const { return false; }; - virtual bool isAttachment() const { return false; }; - virtual bool isHeading() const { return false; }; - virtual bool isLink() const { return false; }; - virtual bool isImage() const { return false; }; - virtual bool isNativeImage() const { return false; }; - virtual bool isImageButton() const { return false; }; - virtual bool isPasswordField() const { return false; }; - virtual bool isTextControl() const { return false; }; - virtual bool isNativeTextControl() const { return false; }; - virtual bool isWebArea() const { return false; }; - virtual bool isCheckboxOrRadio() const { return false; }; - virtual bool isListBox() const { return roleValue() == ListBoxRole; }; - virtual bool isMenuRelated() const { return false; } - virtual bool isMenu() const { return false; } - virtual bool isMenuBar() const { return false; } - virtual bool isMenuButton() const { return false; } - virtual bool isMenuItem() const { return false; } - virtual bool isFileUploadButton() const { return false; }; - virtual bool isProgressIndicator() const { return false; }; - virtual bool isSlider() const { return false; }; - virtual bool isControl() const { return false; }; - virtual bool isList() const { return false; }; - virtual bool isDataTable() const { return false; }; - virtual bool isTableRow() const { return false; }; - virtual bool isTableColumn() const { return false; }; - virtual bool isTableCell() const { return false; }; - virtual bool isFieldset() const { return false; }; - virtual bool isGroup() const { return false; }; - - virtual bool isChecked() const { return false; }; - virtual bool isEnabled() const { return false; }; - virtual bool isSelected() const { return false; }; - virtual bool isFocused() const { return false; }; - virtual bool isHovered() const { return false; }; - virtual bool isIndeterminate() const { return false; }; - virtual bool isLoaded() const { return false; }; - virtual bool isMultiSelect() const { return false; }; - virtual bool isOffScreen() const { return false; }; - virtual bool isPressed() const { return false; }; - virtual bool isReadOnly() const { return false; }; - virtual bool isVisited() const { return false; }; - - virtual bool canSetFocusAttribute() const { return false; }; - virtual bool canSetTextRangeAttributes() const { return false; }; - virtual bool canSetValueAttribute() const { return false; }; - virtual bool canSetSelectedAttribute() const { return false; } - virtual bool canSetSelectedChildrenAttribute() const { return false; } - - virtual bool hasIntValue() const { return false; }; - - bool accessibilityShouldUseUniqueId() const { return true; }; - virtual bool accessibilityIsIgnored() const { return true; }; - - virtual int intValue() const; - virtual float valueForRange() const { return 0.0f; } - virtual float maxValueForRange() const { return 0.0f; } - virtual float minValueForRange() const {return 0.0f; } - virtual int layoutCount() const; - static bool isARIAControl(AccessibilityRole); - static bool isARIAInput(AccessibilityRole); - unsigned axObjectID() const; - - virtual AccessibilityObject* doAccessibilityHitTest(const IntPoint&) const; - virtual AccessibilityObject* focusedUIElement() const; - virtual AccessibilityObject* firstChild() const; - virtual AccessibilityObject* lastChild() const; - virtual AccessibilityObject* previousSibling() const; - virtual AccessibilityObject* nextSibling() const; - virtual AccessibilityObject* parentObject() const; - virtual AccessibilityObject* parentObjectUnignored() const; - virtual AccessibilityObject* observableObject() const; - virtual void linkedUIElements(AccessibilityChildrenVector&) const; - virtual AccessibilityObject* titleUIElement() const; - virtual AccessibilityRole ariaRoleAttribute() const; - virtual bool isPresentationalChildOfAriaRole() const; - virtual bool ariaRoleHasPresentationalChildren() const; - - virtual AccessibilityRole roleValue() const; - virtual AXObjectCache* axObjectCache() const; - - virtual Element* anchorElement() const; - virtual Element* actionElement() const; - virtual IntRect boundingBoxRect() const; - virtual IntRect elementRect() const; - virtual IntSize size() const; - IntPoint clickPoint() const; - - virtual KURL url() const; - virtual PlainTextRange selectedTextRange() const; - virtual Selection selection() const; - unsigned selectionStart() const; - unsigned selectionEnd() const; - virtual String stringValue() const; - virtual String ariaAccessiblityName(const String&) const; - virtual String ariaLabeledByAttribute() const; - virtual String title() const; - virtual String ariaDescribedByAttribute() const; - virtual String accessibilityDescription() const; - virtual String helpText() const; - virtual String textUnderElement() const; - virtual String text() const; - virtual int textLength() const; - virtual PassRefPtr<Range> ariaSelectedTextDOMRange() const; - virtual String selectedText() const; - virtual const AtomicString& accessKey() const; - const String& actionVerb() const; - virtual Widget* widget() const; - virtual Widget* widgetForAttachmentView() const; - virtual Document* document() const { return 0; } - virtual FrameView* topDocumentFrameView() const { return 0; } - virtual FrameView* documentFrameView() const; - - void setAXObjectID(unsigned); - virtual void setFocused(bool); - virtual void setSelectedText(const String&); - virtual void setSelectedTextRange(const PlainTextRange&); - virtual void setValue(const String&); - virtual void setSelected(bool); - - virtual void detach(); - virtual void makeRangeVisible(const PlainTextRange&); - virtual bool press() const; - bool performDefaultAction() const { return press(); } - - virtual void childrenChanged(); - virtual const AccessibilityChildrenVector& children() { return m_children; } - virtual void addChildren(); - virtual bool canHaveChildren() const { return true; } - virtual bool hasChildren() const { return m_haveChildren; }; - virtual void selectedChildren(AccessibilityChildrenVector&); - virtual void visibleChildren(AccessibilityChildrenVector&); - virtual bool shouldFocusActiveDescendant() const { return false; } - virtual AccessibilityObject* activeDescendant() const { return 0; } - virtual void handleActiveDescendantChanged() { } - - virtual VisiblePositionRange visiblePositionRange() const; - virtual VisiblePositionRange visiblePositionRangeForLine(unsigned) const; - - VisiblePositionRange visiblePositionRangeForUnorderedPositions(const VisiblePosition&, const VisiblePosition&) const; - VisiblePositionRange positionOfLeftWord(const VisiblePosition&) const; - VisiblePositionRange positionOfRightWord(const VisiblePosition&) const; - VisiblePositionRange leftLineVisiblePositionRange(const VisiblePosition&) const; - VisiblePositionRange rightLineVisiblePositionRange(const VisiblePosition&) const; - VisiblePositionRange sentenceForPosition(const VisiblePosition&) const; - VisiblePositionRange paragraphForPosition(const VisiblePosition&) const; - VisiblePositionRange styleRangeForPosition(const VisiblePosition&) const; - VisiblePositionRange visiblePositionRangeForRange(const PlainTextRange&) const; - - String stringForVisiblePositionRange(const VisiblePositionRange&) const; - virtual IntRect boundsForVisiblePositionRange(const VisiblePositionRange&) const; - int lengthForVisiblePositionRange(const VisiblePositionRange&) const; - virtual void setSelectedVisiblePositionRange(const VisiblePositionRange&) const; - - virtual VisiblePosition visiblePositionForPoint(const IntPoint&) const; - VisiblePosition nextVisiblePosition(const VisiblePosition&) const; - VisiblePosition previousVisiblePosition(const VisiblePosition&) const; - VisiblePosition nextWordEnd(const VisiblePosition&) const; - VisiblePosition previousWordStart(const VisiblePosition&) const; - VisiblePosition nextLineEndPosition(const VisiblePosition&) const; - VisiblePosition previousLineStartPosition(const VisiblePosition&) const; - VisiblePosition nextSentenceEndPosition(const VisiblePosition&) const; - VisiblePosition previousSentenceStartPosition(const VisiblePosition&) const; - VisiblePosition nextParagraphEndPosition(const VisiblePosition&) const; - VisiblePosition previousParagraphStartPosition(const VisiblePosition&) const; - virtual VisiblePosition visiblePositionForIndex(unsigned indexValue, bool lastIndexOK) const; - - virtual VisiblePosition visiblePositionForIndex(int) const; - virtual int indexForVisiblePosition(const VisiblePosition&) const; - - AccessibilityObject* accessibilityObjectForPosition(const VisiblePosition&) const; - int lineForPosition(const VisiblePosition&) const; - PlainTextRange plainTextRangeForVisiblePositionRange(const VisiblePositionRange&) const; - virtual int index(const VisiblePosition&) const; - - virtual PlainTextRange doAXRangeForLine(unsigned) const; - PlainTextRange doAXRangeForPosition(const IntPoint&) const; - virtual PlainTextRange doAXRangeForIndex(unsigned) const; - PlainTextRange doAXStyleRangeForIndex(unsigned) const; - - virtual String doAXStringForRange(const PlainTextRange&) const; - virtual IntRect doAXBoundsForRange(const PlainTextRange&) const; - - unsigned doAXLineForIndex(unsigned); - -#if HAVE(ACCESSIBILITY) -#if PLATFORM(GTK) - AccessibilityObjectWrapper* wrapper() const; - void setWrapper(AccessibilityObjectWrapper*); -#else - AccessibilityObjectWrapper* wrapper() const { return m_wrapper.get(); } - void setWrapper(AccessibilityObjectWrapper* wrapper) - { - m_wrapper = wrapper; - } -#endif -#endif - - // a platform-specific method for determining if an attachment is ignored -#if HAVE(ACCESSIBILITY) - bool accessibilityIgnoreAttachment() const; -#else - bool accessibilityIgnoreAttachment() const { return true; } -#endif - -protected: - unsigned m_id; - AccessibilityChildrenVector m_children; - mutable bool m_haveChildren; - - virtual void clearChildren(); - virtual void removeAXObjectID(); - virtual bool isDetached() const { return true; } - -#if PLATFORM(MAC) - RetainPtr<AccessibilityObjectWrapper> m_wrapper; -#elif PLATFORM(WIN) - COMPtr<AccessibilityObjectWrapper> m_wrapper; -#elif PLATFORM(GTK) - AtkObject* m_wrapper; -#elif PLATFORM(CHROMIUM) - RefPtr<AccessibilityObjectWrapper> m_wrapper; -#endif -}; - -} // namespace WebCore - -#endif // AccessibilityObject_h diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityRenderObject.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityRenderObject.cpp deleted file mode 100644 index dee7eea..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityRenderObject.cpp +++ /dev/null @@ -1,2387 +0,0 @@ -/* -* Copyright (C) 2008 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. -*/ - -#include "config.h" -#include "AccessibilityRenderObject.h" - -#include "AXObjectCache.h" -#include "AccessibilityListBox.h" -#include "AccessibilityImageMapLink.h" -#include "CharacterNames.h" -#include "EventNames.h" -#include "FloatRect.h" -#include "FocusController.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "HTMLAreaElement.h" -#include "HTMLFrameElementBase.h" -#include "HTMLImageElement.h" -#include "HTMLInputElement.h" -#include "HTMLLabelElement.h" -#include "HTMLMapElement.h" -#include "HTMLOptGroupElement.h" -#include "HTMLOptionElement.h" -#include "HTMLOptionsCollection.h" -#include "HTMLSelectElement.h" -#include "HTMLTextAreaElement.h" -#include "HitTestRequest.h" -#include "HitTestResult.h" -#include "LocalizedStrings.h" -#include "NodeList.h" -#include "NotImplemented.h" -#include "Page.h" -#include "RenderFieldset.h" -#include "RenderFileUploadControl.h" -#include "RenderImage.h" -#include "RenderListBox.h" -#include "RenderListMarker.h" -#include "RenderMenuList.h" -#include "RenderTextControl.h" -#include "RenderTheme.h" -#include "RenderView.h" -#include "RenderWidget.h" -#include "SelectionController.h" -#include "Text.h" -#include "TextIterator.h" -#include "htmlediting.h" -#include "visible_units.h" -#include <wtf/StdLibExtras.h> - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityRenderObject::AccessibilityRenderObject(RenderObject* renderer) - : m_renderer(renderer) - , m_ariaRole(UnknownRole) -{ - setAriaRole(); -#ifndef NDEBUG - m_renderer->setHasAXObject(true); -#endif -} - -AccessibilityRenderObject::~AccessibilityRenderObject() -{ - ASSERT(isDetached()); -} - -PassRefPtr<AccessibilityRenderObject> AccessibilityRenderObject::create(RenderObject* renderer) -{ - return adoptRef(new AccessibilityRenderObject(renderer)); -} - -void AccessibilityRenderObject::detach() -{ - clearChildren(); - AccessibilityObject::detach(); - -#ifndef NDEBUG - if (m_renderer) - m_renderer->setHasAXObject(false); -#endif - m_renderer = 0; -} - -AccessibilityObject* AccessibilityRenderObject::firstChild() const -{ - if (!m_renderer) - return 0; - - RenderObject* firstChild = m_renderer->firstChild(); - if (!firstChild) - return 0; - - return m_renderer->document()->axObjectCache()->get(firstChild); -} - -AccessibilityObject* AccessibilityRenderObject::lastChild() const -{ - if (!m_renderer) - return 0; - - RenderObject* lastChild = m_renderer->lastChild(); - if (!lastChild) - return 0; - - return m_renderer->document()->axObjectCache()->get(lastChild); -} - -AccessibilityObject* AccessibilityRenderObject::previousSibling() const -{ - if (!m_renderer) - return 0; - - RenderObject* previousSibling = m_renderer->previousSibling(); - if (!previousSibling) - return 0; - - return m_renderer->document()->axObjectCache()->get(previousSibling); -} - -AccessibilityObject* AccessibilityRenderObject::nextSibling() const -{ - if (!m_renderer) - return 0; - - RenderObject* nextSibling = m_renderer->nextSibling(); - if (!nextSibling) - return 0; - - return m_renderer->document()->axObjectCache()->get(nextSibling); -} - -AccessibilityObject* AccessibilityRenderObject::parentObject() const -{ - if (!m_renderer) - return 0; - - RenderObject *parent = m_renderer->parent(); - if (!parent) - return 0; - - if (ariaRoleAttribute() == MenuBarRole) - return m_renderer->document()->axObjectCache()->get(parent); - - // menuButton and its corresponding menu are DOM siblings, but Accessibility needs them to be parent/child - if (ariaRoleAttribute() == MenuRole) { - AccessibilityObject* parent = menuButtonForMenu(); - if (parent) - return parent; - } - - return m_renderer->document()->axObjectCache()->get(parent); -} - -bool AccessibilityRenderObject::isWebArea() const -{ - return roleValue() == WebAreaRole; -} - -bool AccessibilityRenderObject::isImageButton() const -{ - return isNativeImage() && roleValue() == ButtonRole; -} - -bool AccessibilityRenderObject::isAnchor() const -{ - return !isNativeImage() && isLink(); -} - -bool AccessibilityRenderObject::isNativeTextControl() const -{ - return m_renderer->isTextField() || m_renderer->isTextArea(); -} - -bool AccessibilityRenderObject::isTextControl() const -{ - AccessibilityRole role = roleValue(); - return role == TextAreaRole || role == TextFieldRole; -} - -bool AccessibilityRenderObject::isNativeImage() const -{ - return m_renderer->isImage(); -} - -bool AccessibilityRenderObject::isImage() const -{ - return roleValue() == ImageRole; -} - -bool AccessibilityRenderObject::isAttachment() const -{ - // 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())); - return isWidget && ariaRoleAttribute() == UnknownRole; -} - -bool AccessibilityRenderObject::isPasswordField() const -{ - ASSERT(m_renderer); - if (!m_renderer->element() || !m_renderer->element()->isHTMLElement()) - return false; - return static_cast<HTMLElement*>(m_renderer->element())->isPasswordField() && ariaRoleAttribute() == UnknownRole; -} - -bool AccessibilityRenderObject::isCheckboxOrRadio() const -{ - AccessibilityRole role = roleValue(); - return role == RadioButtonRole || role == CheckBoxRole; -} - -bool AccessibilityRenderObject::isFileUploadButton() const -{ - if (m_renderer && m_renderer->element() && m_renderer->element()->hasTagName(inputTag)) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element()); - return input->inputType() == HTMLInputElement::FILE; - } - - return false; -} - -bool AccessibilityRenderObject::isProgressIndicator() const -{ - return roleValue() == ProgressIndicatorRole; -} - -bool AccessibilityRenderObject::isSlider() const -{ - return roleValue() == SliderRole; -} - -bool AccessibilityRenderObject::isMenuRelated() const -{ - AccessibilityRole role = roleValue(); - return role == MenuRole || - role == MenuBarRole || - role == MenuButtonRole || - role == MenuItemRole; -} - -bool AccessibilityRenderObject::isMenu() const -{ - return roleValue() == MenuRole; -} - -bool AccessibilityRenderObject::isMenuBar() const -{ - return roleValue() == MenuBarRole; -} - -bool AccessibilityRenderObject::isMenuButton() const -{ - return roleValue() == MenuButtonRole; -} - -bool AccessibilityRenderObject::isMenuItem() const -{ - return roleValue() == MenuItemRole; -} - -bool AccessibilityRenderObject::isPressed() const -{ - ASSERT(m_renderer); - if (roleValue() != ButtonRole) - return false; - - Node* node = m_renderer->node(); - if (!node) - return false; - - // If this is an ARIA button, check the aria-pressed attribute rather than node()->active() - if (ariaRoleAttribute() == ButtonRole) { - if (equalIgnoringCase(getAttribute(aria_pressedAttr).string(), "true")) - return true; - return false; - } - - return node->active(); -} - -bool AccessibilityRenderObject::isIndeterminate() const -{ - ASSERT(m_renderer); - return m_renderer->node() && m_renderer->node()->isIndeterminate(); -} - -bool AccessibilityRenderObject::isChecked() const -{ - ASSERT(m_renderer); - return m_renderer->node() && m_renderer->node()->isChecked(); -} - -bool AccessibilityRenderObject::isHovered() const -{ - ASSERT(m_renderer); - return m_renderer->node() && m_renderer->node()->hovered(); -} - -bool AccessibilityRenderObject::isMultiSelect() const -{ - ASSERT(m_renderer); - if (!m_renderer->isListBox()) - return false; - return m_renderer->element() && static_cast<HTMLSelectElement*>(m_renderer->element())->multiple(); -} - -bool AccessibilityRenderObject::isReadOnly() const -{ - ASSERT(m_renderer); - - if (isWebArea()) { - Document* document = m_renderer->document(); - if (!document) - return true; - - HTMLElement* body = document->body(); - if (body && body->isContentEditable()) - return false; - - Frame* frame = document->frame(); - if (!frame) - return true; - - return !frame->isContentEditable(); - } - - return !m_renderer->node() || !m_renderer->node()->isContentEditable(); -} - -bool AccessibilityRenderObject::isOffScreen() const -{ - ASSERT(m_renderer); - IntRect contentRect = m_renderer->absoluteClippedOverflowRect(); - FrameView* view = m_renderer->document()->frame()->view(); - FloatRect viewRect = view->visibleContentRect(); - viewRect.intersect(contentRect); - return viewRect.isEmpty(); -} - -int AccessibilityRenderObject::headingLevel(Node* node) -{ - // headings can be in block flow and non-block flow - if (!node) - return 0; - - if (RenderObject* renderer = node->renderer()) { - AccessibilityObject* axObjectForNode = node->document()->axObjectCache()->get(renderer); - if (axObjectForNode->ariaRoleAttribute() == HeadingRole) { - if (!node->isElementNode()) - return 0; - Element* element = static_cast<Element*>(node); - return element->getAttribute(aria_levelAttr).toInt(); - } - } - - - if (node->hasTagName(h1Tag)) - return 1; - - if (node->hasTagName(h2Tag)) - return 2; - - if (node->hasTagName(h3Tag)) - return 3; - - if (node->hasTagName(h4Tag)) - return 4; - - if (node->hasTagName(h5Tag)) - return 5; - - if (node->hasTagName(h6Tag)) - return 6; - - return 0; -} - -bool AccessibilityRenderObject::isHeading() const -{ - return roleValue() == HeadingRole; -} - -bool AccessibilityRenderObject::isLink() const -{ - return roleValue() == WebCoreLinkRole; -} - -bool AccessibilityRenderObject::isControl() const -{ - if (!m_renderer) - return false; - - Node* node = m_renderer->element(); - return node && (node->isControl() || AccessibilityObject::isARIAControl(ariaRoleAttribute())); -} - -bool AccessibilityRenderObject::isFieldset() const -{ - if (!m_renderer) - return false; - - return m_renderer->isFieldset(); -} - -bool AccessibilityRenderObject::isGroup() const -{ - return roleValue() == GroupRole; -} - -const AtomicString& AccessibilityRenderObject::getAttribute(const QualifiedName& attribute) const -{ - Node* node = m_renderer->element(); - if (!node) - return nullAtom; - - if (!node->isElementNode()) - return nullAtom; - - Element* element = static_cast<Element*>(node); - return element->getAttribute(attribute); -} - -Element* AccessibilityRenderObject::anchorElement() const -{ - if (!m_renderer) - return 0; - - AXObjectCache* cache = axObjectCache(); - 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()) { - if (currRenderer->continuation()) - return cache->get(currRenderer->continuation())->anchorElement(); - } - - // bail if none found - if (!currRenderer) - return 0; - - // search up the DOM tree for an anchor element - // 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())) - return static_cast<Element*>(node); - } - - return 0; -} - -Element* AccessibilityRenderObject::actionElement() const -{ - if (m_renderer->element() && m_renderer->element()->hasTagName(inputTag)) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element()); - if (!input->disabled() && (isCheckboxOrRadio() || input->isTextButton())) - return input; - } - - if (isFileUploadButton()) - return static_cast<Element*>(m_renderer->element()); - - if (AccessibilityObject::isARIAInput(ariaRoleAttribute())) - return static_cast<Element*>(m_renderer->element()); - - if (isImageButton()) - return static_cast<Element*>(m_renderer->element()); - - if (m_renderer->isMenuList()) - return static_cast<RenderMenuList*>(m_renderer)->selectElement(); - - Element* elt = anchorElement(); - if (!elt) - elt = mouseButtonListener(); - return elt; -} - -Element* AccessibilityRenderObject::mouseButtonListener() const -{ - Node* node = m_renderer->element(); - if (!node) - return 0; - if (!node->isEventTargetNode()) - 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); - } - - return 0; -} - -static Element* siblingWithAriaRole(String role, Node* node) -{ - Node* sibling = node->parent()->firstChild(); - while (sibling) { - if (sibling->isElementNode()) { - String siblingAriaRole = static_cast<Element*>(sibling)->getAttribute(roleAttr).string(); - if (equalIgnoringCase(siblingAriaRole, role)) - return static_cast<Element*>(sibling); - } - sibling = sibling->nextSibling(); - } - - return 0; -} - -Element* AccessibilityRenderObject::menuElementForMenuButton() const -{ - if (ariaRoleAttribute() != MenuButtonRole) - return 0; - - return siblingWithAriaRole("menu", renderer()->node()); -} - -AccessibilityObject* AccessibilityRenderObject::menuForMenuButton() const -{ - Element* menu = menuElementForMenuButton(); - if (menu && menu->renderer()) - return m_renderer->document()->axObjectCache()->get(menu->renderer()); - return 0; -} - -Element* AccessibilityRenderObject::menuItemElementForMenu() const -{ - if (ariaRoleAttribute() != MenuRole) - return 0; - - return siblingWithAriaRole("menuitem", renderer()->node()); -} - -AccessibilityObject* AccessibilityRenderObject::menuButtonForMenu() const -{ - Element* menuItem = menuItemElementForMenu(); - - 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()); - if (menuItemAX->isMenuButton()) - return menuItemAX; - } - return 0; -} - -String AccessibilityRenderObject::helpText() const -{ - if (!m_renderer) - 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 (!summary.isEmpty()) - return summary; - const AtomicString& title = static_cast<Element*>(curr->element())->getAttribute(titleAttr); - if (!title.isEmpty()) - return title; - } - } - - return String(); -} - -String AccessibilityRenderObject::textUnderElement() const -{ - if (!m_renderer) - return String(); - - if (isFileUploadButton()) { - RenderFileUploadControl* uploadControl = static_cast<RenderFileUploadControl*>(m_renderer); - return uploadControl->buttonValue(); - } - - Node* node = m_renderer->element(); - if (node) { - if (Frame* frame = node->document()->frame()) { - // catch stale WebCoreAXObject (see <rdar://problem/3960196>) - if (frame->document() != node->document()) - return String(); - return plainText(rangeOfContents(node).get()); - } - } - - // return the null string for anonymous text because it is non-trivial to get - // the actual text and, so far, that is not needed - return String(); -} - -bool AccessibilityRenderObject::hasIntValue() const -{ - if (isHeading()) - return true; - - if (m_renderer->element() && isCheckboxOrRadio()) - return true; - - return false; -} - -int AccessibilityRenderObject::intValue() const -{ - if (!m_renderer || isPasswordField()) - return 0; - - if (isHeading()) - return headingLevel(m_renderer->element()); - - Node* node = m_renderer->element(); - if (!node || !isCheckboxOrRadio()) - return 0; - - // If this is an ARIA checkbox or radio, check the aria-checked attribute rather than node()->checked() - AccessibilityRole ariaRole = ariaRoleAttribute(); - if (ariaRole == RadioButtonRole || ariaRole == CheckBoxRole) { - if (equalIgnoringCase(getAttribute(aria_checkedAttr).string(), "true")) - return true; - return false; - } - - return static_cast<HTMLInputElement*>(node)->checked(); -} - -float AccessibilityRenderObject::valueForRange() const -{ - if (!isProgressIndicator() && !isSlider()) - return 0.0f; - - return getAttribute(aria_valuenowAttr).toFloat(); -} - -float AccessibilityRenderObject::maxValueForRange() const -{ - if (!isProgressIndicator() && !isSlider()) - return 0.0f; - - return getAttribute(aria_valuemaxAttr).toFloat(); -} - -float AccessibilityRenderObject::minValueForRange() const -{ - if (!isProgressIndicator() && !isSlider()) - return 0.0f; - - return getAttribute(aria_valueminAttr).toFloat(); -} - -String AccessibilityRenderObject::stringValue() const -{ - if (!m_renderer || isPasswordField()) - return String(); - - if (m_renderer->isText()) - return textUnderElement(); - - if (m_renderer->isMenuList()) - return static_cast<RenderMenuList*>(m_renderer)->text(); - - if (m_renderer->isListMarker()) - return static_cast<RenderListMarker*>(m_renderer)->text(); - - if (isWebArea()) { - if (m_renderer->document()->frame()) - return String(); - - // FIXME: should use startOfDocument and endOfDocument (or rangeForDocument?) here - VisiblePosition startVisiblePosition = m_renderer->positionForCoordinates(0, 0); - VisiblePosition endVisiblePosition = m_renderer->positionForCoordinates(INT_MAX, INT_MAX); - if (startVisiblePosition.isNull() || endVisiblePosition.isNull()) - return String(); - - return plainText(makeRange(startVisiblePosition, endVisiblePosition).get()); - } - - if (isTextControl()) - return text(); - - if (isFileUploadButton()) { - RenderFileUploadControl* uploadControl = static_cast<RenderFileUploadControl*>(m_renderer); - return uploadControl->fileTextValue(); - } - - // FIXME: We might need to implement a value here for more types - // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one; - // this would require subclassing or making accessibilityAttributeNames do something other than return a - // single static array. - return String(); -} - -// This function implements the ARIA accessible name as described by the Mozilla -// ARIA Implementer's Guide. -static String accessibleNameForNode(Node* node) -{ - if (node->isTextNode()) - return static_cast<Text*>(node)->data(); - - if (node->hasTagName(inputTag)) - return static_cast<HTMLInputElement*>(node)->value(); - - if (node->isHTMLElement()) { - const AtomicString& alt = static_cast<HTMLElement*>(node)->getAttribute(altAttr); - if (!alt.isEmpty()) - return alt; - } - - return String(); -} - -String AccessibilityRenderObject::ariaAccessiblityName(const String& s) const -{ - Document* document = m_renderer->document(); - if (!document) - return String(); - - String idList = s; - idList.replace('\n', ' '); - Vector<String> idVector; - idList.split(' ', idVector); - - Vector<UChar> ariaLabel; - unsigned size = idVector.size(); - for (unsigned i = 0; i < size; ++i) { - String idName = idVector[i]; - Element* idElement = document->getElementById(idName); - if (idElement) { - String nameFragment = accessibleNameForNode(idElement); - ariaLabel.append(nameFragment.characters(), nameFragment.length()); - for (Node* n = idElement->firstChild(); n; n = n->traverseNextNode(idElement->nextSibling())) { - nameFragment = accessibleNameForNode(n); - ariaLabel.append(nameFragment.characters(), nameFragment.length()); - } - ariaLabel.append(' '); - } - } - return String::adopt(ariaLabel); -} - -String AccessibilityRenderObject::ariaLabeledByAttribute() const -{ - Node* node = m_renderer->node(); - if (!node) - return String(); - - if (!node->isElementNode()) - return String(); - - // The ARIA spec uses the British spelling: "labelled." It seems prudent to support the American - // spelling ("labeled") as well. - String idList = getAttribute(aria_labeledbyAttr).string(); - if (idList.isEmpty()) { - idList = getAttribute(aria_labelledbyAttr).string(); - if (idList.isEmpty()) - return String(); - } - - return ariaAccessiblityName(idList); -} - -static HTMLLabelElement* labelForElement(Element* element) -{ - RefPtr<NodeList> list = element->document()->getElementsByTagName("label"); - unsigned len = list->length(); - for (unsigned i = 0; i < len; i++) { - if (list->item(i)->hasTagName(labelTag)) { - HTMLLabelElement* label = static_cast<HTMLLabelElement*>(list->item(i)); - if (label->correspondingControl() == element) - return label; - } - } - - return 0; -} - -HTMLLabelElement* AccessibilityRenderObject::labelElementContainer() const -{ - if (!m_renderer) - return false; - - // the control element should not be considered part of the label - if (isControl()) - return false; - - // find if this has a parent that is a label - for (Node* parentNode = m_renderer->element(); parentNode; parentNode = parentNode->parentNode()) { - if (parentNode->hasTagName(labelTag)) - return static_cast<HTMLLabelElement*>(parentNode); - } - - return 0; -} - -String AccessibilityRenderObject::title() const -{ - AccessibilityRole ariaRole = ariaRoleAttribute(); - - if (!m_renderer) - return String(); - - Node* node = m_renderer->element(); - if (!node) - return String(); - - String ariaLabel = ariaLabeledByAttribute(); - if (!ariaLabel.isEmpty()) - return ariaLabel; - - const AtomicString& title = getAttribute(titleAttr); - if (!title.isEmpty()) - return title; - - bool isInputTag = node->hasTagName(inputTag); - if (isInputTag) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(node); - if (input->isTextButton()) - return input->value(); - } - - if (isInputTag || AccessibilityObject::isARIAInput(ariaRole) || isControl()) { - HTMLLabelElement* label = labelForElement(static_cast<Element*>(node)); - if (label) - return label->innerText(); - } - - if (roleValue() == ButtonRole - || ariaRole == ListBoxOptionRole - || ariaRole == MenuItemRole - || ariaRole == MenuButtonRole - || isHeading()) - return textUnderElement(); - - if (isLink()) - return textUnderElement(); - - return String(); -} - -String AccessibilityRenderObject::ariaDescribedByAttribute() const -{ - String idList = getAttribute(aria_describedbyAttr).string(); - if (idList.isEmpty()) - return String(); - - return ariaAccessiblityName(idList); -} - -String AccessibilityRenderObject::accessibilityDescription() const -{ - if (!m_renderer) - return String(); - - String ariaDescription = ariaDescribedByAttribute(); - 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 (alt.isEmpty()) - return String(); - return alt; - } - } - - if (isWebArea()) { - Document *document = m_renderer->document(); - Node* owner = document->ownerElement(); - if (owner) { - if (owner->hasTagName(frameTag) || owner->hasTagName(iframeTag)) { - const AtomicString& title = static_cast<HTMLFrameElementBase*>(owner)->getAttribute(titleAttr); - if (!title.isEmpty()) - return title; - return static_cast<HTMLFrameElementBase*>(owner)->name(); - } - if (owner->isHTMLElement()) - return static_cast<HTMLElement*>(owner)->getAttribute(nameAttr); - } - owner = document->body(); - if (owner && owner->isHTMLElement()) - return static_cast<HTMLElement*>(owner)->getAttribute(nameAttr); - } - - if (roleValue() == DefinitionListTermRole) - return AXDefinitionListTermText(); - if (roleValue() == DefinitionListDefinitionRole) - return AXDefinitionListDefinitionText(); - - return String(); -} - -IntRect AccessibilityRenderObject::boundingBoxRect() const -{ - IntRect rect; - RenderObject* obj = m_renderer; - - if (!obj) - return IntRect(); - - if (obj->isInlineContinuation()) - obj = obj->element()->renderer(); - - // FIXME: This doesn't work correctly with transforms. - Vector<IntRect> rects; - FloatPoint absPos = obj->localToAbsolute(); - obj->absoluteRects(rects, absPos.x(), absPos.y()); - const size_t n = rects.size(); - for (size_t i = 0; i < n; ++i) { - IntRect r = rects[i]; - if (!r.isEmpty()) { - if (obj->style()->hasAppearance()) - theme()->adjustRepaintRect(obj, r); - rect.unite(r); - } - } - return rect; -} - -IntRect AccessibilityRenderObject::checkboxOrRadioRect() const -{ - if (!m_renderer) - return IntRect(); - - HTMLLabelElement* label = labelForElement(static_cast<Element*>(m_renderer->element())); - if (!label || !label->renderer()) - return boundingBoxRect(); - - IntRect labelRect = axObjectCache()->get(label->renderer())->elementRect(); - labelRect.unite(boundingBoxRect()); - return labelRect; -} - -IntRect AccessibilityRenderObject::elementRect() const -{ - // a checkbox or radio button should encompass its label - if (isCheckboxOrRadio()) - return checkboxOrRadioRect(); - - return boundingBoxRect(); -} - -IntSize AccessibilityRenderObject::size() const -{ - IntRect rect = elementRect(); - return rect.size(); -} - -AccessibilityObject* AccessibilityRenderObject::internalLinkElement() const -{ - Element* element = anchorElement(); - if (!element) - return 0; - - // Right now, we do not support ARIA links as internal link elements - if (!element->hasTagName(aTag)) - return 0; - HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(element); - - KURL linkURL = anchor->href(); - String ref = linkURL.ref(); - if (ref.isEmpty()) - return 0; - - // check if URL is the same as current URL - linkURL.removeRef(); - if (m_renderer->document()->url() != linkURL) - return 0; - - Node* linkedNode = m_renderer->document()->findAnchor(ref); - if (!linkedNode) - 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()); - while (linkedAXElement && linkedAXElement->accessibilityIsIgnored()) { - linkedNode = linkedNode->traverseNextNode(); - - while (linkedNode && !linkedNode->renderer()) - linkedNode = linkedNode->traverseNextSibling(); - - if (!linkedNode) - return 0; - linkedAXElement = m_renderer->document()->axObjectCache()->get(linkedNode->renderer()); - } - - return linkedAXElement; -} - -void AccessibilityRenderObject::addRadioButtonGroupMembers(AccessibilityChildrenVector& linkedUIElements) const -{ - if (!m_renderer || roleValue() != RadioButtonRole) - return; - - Node* node = m_renderer->node(); - if (!node || !node->hasTagName(inputTag)) - return; - - HTMLInputElement* input = static_cast<HTMLInputElement*>(node); - // if there's a form, then this is easy - if (input->form()) { - Vector<RefPtr<Node> > formElements; - input->form()->getNamedElements(input->name(), formElements); - - 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())) - linkedUIElements.append(object); - } - } else { - RefPtr<NodeList> list = node->document()->getElementsByTagName("input"); - unsigned len = list->length(); - for (unsigned i = 0; i < len; ++i) { - 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())) - linkedUIElements.append(object); - } - } - } - } -} - -// linked ui elements could be all the related radio buttons in a group -// or an internal anchor connection -void AccessibilityRenderObject::linkedUIElements(AccessibilityChildrenVector& linkedUIElements) const -{ - if (isAnchor()) { - AccessibilityObject* linkedAXElement = internalLinkElement(); - if (linkedAXElement) - linkedUIElements.append(linkedAXElement); - } - - if (roleValue() == RadioButtonRole) - addRadioButtonGroupMembers(linkedUIElements); -} - -AccessibilityObject* AccessibilityRenderObject::titleUIElement() const -{ - if (!m_renderer) - return 0; - - // if isFieldset is true, the renderer is guaranteed to be a RenderFieldset - if (isFieldset()) - return axObjectCache()->get(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(); - HTMLLabelElement* label = labelForElement(static_cast<Element*>(element)); - if (label && label->renderer()) - return axObjectCache()->get(label->renderer()); - - return 0; -} - -bool AccessibilityRenderObject::accessibilityIsIgnored() const -{ - // ignore invisible element - if (!m_renderer || m_renderer->style()->visibility() != VISIBLE) - return true; - - if (isPresentationalChildOfAriaRole()) - return true; - - // ignore popup menu items because AppKit does - for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) { - if (parent->isMenuList()) - return true; - } - - // find out if this element is inside of a label element. - // if so, it may be ignored because it's the label for a checkbox or radio button - HTMLLabelElement* labelElement = labelElementContainer(); - if (labelElement) { - HTMLElement* correspondingControl = labelElement->correspondingControl(); - if (correspondingControl && correspondingControl->renderer()) { - AccessibilityObject* controlObject = axObjectCache()->get(correspondingControl->renderer()); - if (controlObject->isCheckboxOrRadio()) - return true; - } - } - - AccessibilityRole ariaRole = ariaRoleAttribute(); - if (ariaRole == TextAreaRole || ariaRole == StaticTextRole) { - String ariaText = text(); - return ariaText.isNull() || ariaText.isEmpty(); - } - - // NOTE: BRs always have text boxes now, so the text box check here can be removed - if (m_renderer->isText()) { - // static text beneath MenuItems and MenuButtons are just reported along with the menu item, so it's ignored on an individual level - if (parentObjectUnignored()->ariaRoleAttribute() == MenuItemRole || - parentObjectUnignored()->ariaRoleAttribute() == MenuButtonRole) - return true; - return m_renderer->isBR() || !static_cast<RenderText*>(m_renderer)->firstTextBox(); - } - - if (isHeading()) - return false; - - if (isLink()) - return false; - - // all controls are accessible - if (isControl()) - return false; - - // don't ignore labels, because they serve as TitleUIElements - Node* node = m_renderer->element(); - if (node && node->hasTagName(labelTag)) - return false; - - if (m_renderer->isBlockFlow() && m_renderer->childrenInline()) - return !static_cast<RenderBlock*>(m_renderer)->firstLineBox() && !mouseButtonListener(); - - // ignore images seemingly used as spacers - if (isImage()) { - if (node && node->isElementNode()) { - Element* elt = static_cast<Element*>(node); - const AtomicString& alt = elt->getAttribute(altAttr); - // don't ignore an image that has an alt tag - if (!alt.isEmpty()) - return false; - // informal standard is to ignore images with zero-length alt strings - if (!alt.isNull()) - return true; - } - - // check for one-dimensional image - if (m_renderer->height() <= 1 || m_renderer->width() <= 1) - return true; - - // check whether rendered image was stretched from one-dimensional file image - if (isNativeImage()) { - RenderImage* image = static_cast<RenderImage*>(m_renderer); - if (image->cachedImage()) { - IntSize imageSize = image->cachedImage()->imageSize(image->view()->zoomFactor()); - return imageSize.height() <= 1 || imageSize.width() <= 1; - } - } - return false; - } - - if (ariaRole != UnknownRole) - return false; - - // make a platform-specific decision - if (isAttachment()) - return accessibilityIgnoreAttachment(); - - return !m_renderer->isListMarker() && !isWebArea(); -} - -bool AccessibilityRenderObject::isLoaded() const -{ - return !m_renderer->document()->tokenizer(); -} - -int AccessibilityRenderObject::layoutCount() const -{ - if (!m_renderer->isRenderView()) - return 0; - return static_cast<RenderView*>(m_renderer)->frameView()->layoutCount(); -} - -String AccessibilityRenderObject::text() const -{ - if (!isTextControl() || isPasswordField()) - return String(); - - if (isNativeTextControl()) - return static_cast<RenderTextControl*>(m_renderer)->text(); - - Node* node = m_renderer->element(); - if (!node) - return String(); - if (!node->isElementNode()) - return String(); - - return static_cast<Element*>(node)->innerText(); -} - -int AccessibilityRenderObject::textLength() const -{ - ASSERT(isTextControl()); - - if (isPasswordField()) - return -1; // need to return something distinct from 0 - - return text().length(); -} - -PassRefPtr<Range> AccessibilityRenderObject::ariaSelectedTextDOMRange() const -{ - Node* node = m_renderer->element(); - if (!node) - return 0; - - RefPtr<Range> currentSelectionRange = selection().toRange(); - if (!currentSelectionRange) - return 0; - - ExceptionCode ec = 0; - if (!currentSelectionRange->intersectsNode(node, ec)) - return Range::create(currentSelectionRange->ownerDocument()); - - RefPtr<Range> ariaRange = rangeOfContents(node); - Position startPosition, endPosition; - - // Find intersection of currentSelectionRange and ariaRange - if (ariaRange->startOffset() > currentSelectionRange->startOffset()) - startPosition = ariaRange->startPosition(); - else - startPosition = currentSelectionRange->startPosition(); - - if (ariaRange->endOffset() < currentSelectionRange->endOffset()) - endPosition = ariaRange->endPosition(); - else - endPosition = currentSelectionRange->endPosition(); - - return Range::create(ariaRange->ownerDocument(), startPosition, endPosition); -} - -String AccessibilityRenderObject::selectedText() const -{ - ASSERT(isTextControl()); - - if (isPasswordField()) - return String(); // need to return something distinct from empty string - - if (isNativeTextControl()) { - RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer); - return textControl->text().substring(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart()); - } - - if (ariaRoleAttribute() == UnknownRole) - return String(); - - RefPtr<Range> ariaRange = ariaSelectedTextDOMRange(); - if (!ariaRange) - return String(); - return ariaRange->text(); -} - -const AtomicString& AccessibilityRenderObject::accessKey() const -{ - Node* node = m_renderer->element(); - if (!node) - return nullAtom; - if (!node->isElementNode()) - return nullAtom; - return static_cast<Element*>(node)->getAttribute(accesskeyAttr); -} - -Selection AccessibilityRenderObject::selection() const -{ - return m_renderer->document()->frame()->selection()->selection(); -} - -PlainTextRange AccessibilityRenderObject::selectedTextRange() const -{ - ASSERT(isTextControl()); - - if (isPasswordField()) - return PlainTextRange(); - - AccessibilityRole ariaRole = ariaRoleAttribute(); - if (isNativeTextControl() && ariaRole == UnknownRole) { - RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer); - return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart()); - } - - if (ariaRole == UnknownRole) - return PlainTextRange(); - - RefPtr<Range> ariaRange = ariaSelectedTextDOMRange(); - if (!ariaRange) - return PlainTextRange(); - return PlainTextRange(ariaRange->startOffset(), ariaRange->endOffset()); -} - -void AccessibilityRenderObject::setSelectedTextRange(const PlainTextRange& range) -{ - if (isNativeTextControl()) { - RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer); - textControl->setSelectionRange(range.start, range.start + range.length); - return; - } - - Document* document = m_renderer->document(); - if (!document) - return; - Frame* frame = document->frame(); - if (!frame) - return; - Node* node = m_renderer->element(); - frame->selection()->setSelection(Selection(Position(node, range.start), - Position(node, range.start + range.length), DOWNSTREAM)); -} - -KURL AccessibilityRenderObject::url() const -{ - if (isAnchor() && m_renderer->element()->hasTagName(aTag)) { - if (HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(anchorElement())) - return anchor->href(); - } - - 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(); - - return KURL(); -} - -bool AccessibilityRenderObject::isVisited() const -{ - return m_renderer->style()->pseudoState() == PseudoVisited; -} - -bool AccessibilityRenderObject::isSelected() const -{ - if (!m_renderer) - return false; - - Node* node = m_renderer->node(); - if (!node) - return false; - - return false; -} - -bool AccessibilityRenderObject::isFocused() const -{ - if (!m_renderer) - return false; - - Document* document = m_renderer->document(); - if (!document) - return false; - - Node* focusedNode = document->focusedNode(); - if (!focusedNode) - return false; - - // 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() || - (roleValue() == WebAreaRole && document->frame()->selection()->isFocusedAndActive())) - return true; - - return false; -} - -void AccessibilityRenderObject::setFocused(bool on) -{ - if (!canSetFocusAttribute()) - return; - - if (!on) - m_renderer->document()->setFocusedNode(0); - else { - if (m_renderer->element()->isElementNode()) - static_cast<Element*>(m_renderer->element())->focus(); - else - m_renderer->document()->setFocusedNode(m_renderer->element()); - } -} - -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()); - input->setValue(string); - } else if (m_renderer->isTextArea()) { - HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(m_renderer->element()); - textArea->setValue(string); - } -} - -bool AccessibilityRenderObject::isEnabled() const -{ - return m_renderer->element() ? m_renderer->element()->isEnabled() : true; -} - -RenderObject* AccessibilityRenderObject::topRenderer() const -{ - return m_renderer->document()->topDocument()->renderer(); -} - -Document* AccessibilityRenderObject::document() const -{ - return m_renderer->document(); -} - -FrameView* AccessibilityRenderObject::topDocumentFrameView() const -{ - return topRenderer()->view()->frameView(); -} - -Widget* AccessibilityRenderObject::widget() const -{ - if (!m_renderer->isWidget()) - return 0; - - return static_cast<RenderWidget*>(m_renderer)->widget(); -} - -AXObjectCache* AccessibilityRenderObject::axObjectCache() const -{ - return m_renderer->document()->axObjectCache(); -} - -AccessibilityObject* AccessibilityRenderObject::accessibilityParentForImageMap(HTMLMapElement* map) const -{ - // find an image that is using this map - if (!m_renderer || !map) - return 0; - - RefPtr<HTMLCollection> coll = m_renderer->document()->images(); - for (Node* curr = coll->firstItem(); curr; curr = coll->nextItem()) { - RenderObject* obj = curr->renderer(); - if (!obj || !curr->hasTagName(imgTag)) - continue; - - // 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 0; -} - -void AccessibilityRenderObject::getDocumentLinks(AccessibilityChildrenVector& result) -{ - Document* document = m_renderer->document(); - RefPtr<HTMLCollection> coll = document->links(); - Node* curr = coll->firstItem(); - while (curr) { - RenderObject* obj = curr->renderer(); - if (obj) { - RefPtr<AccessibilityObject> axobj = document->axObjectCache()->get(obj); - ASSERT(axobj); - ASSERT(axobj->roleValue() == WebCoreLinkRole); - if (!axobj->accessibilityIsIgnored()) - result.append(axobj); - } else { - Node* parent = curr->parent(); - if (parent && curr->hasTagName(areaTag) && parent->hasTagName(mapTag)) { - AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(axObjectCache()->get(ImageMapLinkRole)); - areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(curr)); - areaObject->setHTMLMapElement(static_cast<HTMLMapElement*>(parent)); - areaObject->setParent(accessibilityParentForImageMap(static_cast<HTMLMapElement*>(parent))); - - result.append(areaObject); - } - } - curr = coll->nextItem(); - } -} - -FrameView* AccessibilityRenderObject::documentFrameView() const -{ - if (!m_renderer || !m_renderer->document()) - return 0; - - // this is the RenderObject's Document's Frame's FrameView - return m_renderer->document()->view(); -} - -Widget* AccessibilityRenderObject::widgetForAttachmentView() const -{ - if (!isAttachment()) - return 0; - return static_cast<RenderWidget*>(m_renderer)->widget(); -} - -FrameView* AccessibilityRenderObject::frameViewIfRenderView() const -{ - if (!m_renderer->isRenderView()) - return 0; - // this is the RenderObject's Document's renderer's FrameView - return m_renderer->view()->frameView(); -} - -// This function is like a cross-platform version of - (WebCoreTextMarkerRange*)textMarkerRange. It returns -// a Range that we can convert to a WebCoreTextMarkerRange in the Obj-C file -VisiblePositionRange AccessibilityRenderObject::visiblePositionRange() const -{ - if (!m_renderer) - return VisiblePositionRange(); - - // construct VisiblePositions for start and end - Node* node = m_renderer->element(); - if (!node) - return VisiblePositionRange(); - - VisiblePosition startPos = VisiblePosition(node, 0, VP_DEFAULT_AFFINITY); - VisiblePosition endPos = VisiblePosition(node, maxDeepOffset(node), VP_DEFAULT_AFFINITY); - - // the VisiblePositions are equal for nodes like buttons, so adjust for that - if (startPos == endPos) { - endPos = endPos.next(); - if (endPos.isNull()) - endPos = startPos; - } - - return VisiblePositionRange(startPos, endPos); -} - -VisiblePositionRange AccessibilityRenderObject::visiblePositionRangeForLine(unsigned lineCount) const -{ - if (lineCount == 0 || !m_renderer) - return VisiblePositionRange(); - - // iterate over the lines - // FIXME: this is wrong when lineNumber is lineCount+1, because nextLinePosition takes you to the - // last offset of the last line - VisiblePosition visiblePos = m_renderer->document()->renderer()->positionForCoordinates(0, 0); - VisiblePosition savedVisiblePos; - while (--lineCount != 0) { - savedVisiblePos = visiblePos; - visiblePos = nextLinePosition(visiblePos, 0); - if (visiblePos.isNull() || visiblePos == savedVisiblePos) - return VisiblePositionRange(); - } - - // make a caret selection for the marker position, then extend it to the line - // NOTE: ignores results of sel.modify because it returns false when - // starting at an empty line. The resulting selection in that case - // will be a caret at visiblePos. - SelectionController selection; - selection.setSelection(Selection(visiblePos)); - selection.modify(SelectionController::EXTEND, SelectionController::RIGHT, LineBoundary); - - return VisiblePositionRange(selection.selection().visibleStart(), selection.selection().visibleEnd()); -} - -VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(int index) const -{ - if (!m_renderer) - return VisiblePosition(); - - if (isNativeTextControl()) - return static_cast<RenderTextControl*>(m_renderer)->visiblePositionForIndex(index); - - if (!isTextControl() && !m_renderer->isText()) - return VisiblePosition(); - - Node* node = m_renderer->node(); - if (!node) - return VisiblePosition(); - - if (index <= 0) - return VisiblePosition(node, 0, DOWNSTREAM); - - ExceptionCode ec = 0; - RefPtr<Range> range = Range::create(m_renderer->document()); - range->selectNodeContents(node, ec); - CharacterIterator it(range.get()); - it.advance(index - 1); - return VisiblePosition(it.range()->endContainer(ec), it.range()->endOffset(ec), UPSTREAM); -} - -int AccessibilityRenderObject::indexForVisiblePosition(const VisiblePosition& pos) const -{ - if (isNativeTextControl()) - return static_cast<RenderTextControl*>(m_renderer)->indexForVisiblePosition(pos); - - if (!isTextControl()) - return 0; - - Node* node = m_renderer->node(); - if (!node) - return 0; - - Position indexPosition = pos.deepEquivalent(); - if (!indexPosition.node() || indexPosition.node()->rootEditableElement() != node) - return 0; - - ExceptionCode ec = 0; - RefPtr<Range> range = Range::create(m_renderer->document()); - range->setStart(node, 0, ec); - range->setEnd(indexPosition.node(), indexPosition.offset(), ec); - return TextIterator::rangeLength(range.get()); -} - -IntRect AccessibilityRenderObject::boundsForVisiblePositionRange(const VisiblePositionRange& visiblePositionRange) const -{ - if (visiblePositionRange.isNull()) - return IntRect(); - - // Create a mutable VisiblePositionRange. - VisiblePositionRange range(visiblePositionRange); - IntRect rect1 = range.start.absoluteCaretBounds(); - IntRect rect2 = range.end.absoluteCaretBounds(); - - // readjust for position at the edge of a line. This is to exclude line rect that doesn't need to be accounted in the range bounds - if (rect2.y() != rect1.y()) { - VisiblePosition endOfFirstLine = endOfLine(range.start); - if (range.start == endOfFirstLine) { - range.start.setAffinity(DOWNSTREAM); - rect1 = range.start.absoluteCaretBounds(); - } - if (range.end == endOfFirstLine) { - range.end.setAffinity(UPSTREAM); - rect2 = range.end.absoluteCaretBounds(); - } - } - - IntRect ourrect = rect1; - ourrect.unite(rect2); - - // if the rectangle spans lines and contains multiple text chars, use the range's bounding box intead - if (rect1.bottom() != rect2.bottom()) { - RefPtr<Range> dataRange = makeRange(range.start, range.end); - IntRect boundingBox = dataRange->boundingBox(); - String rangeString = plainText(dataRange.get()); - if (rangeString.length() > 1 && !boundingBox.isEmpty()) - ourrect = boundingBox; - } - -#if PLATFORM(MAC) - return m_renderer->document()->view()->contentsToScreen(ourrect); -#else - return ourrect; -#endif -} - -void AccessibilityRenderObject::setSelectedVisiblePositionRange(const VisiblePositionRange& range) const -{ - if (range.start.isNull() || range.end.isNull()) - return; - - // make selection and tell the document to use it. if it's zero length, then move to that position - if (range.start == range.end) { - m_renderer->document()->frame()->selection()->moveTo(range.start, true); - } - else { - Selection newSelection = Selection(range.start, range.end); - m_renderer->document()->frame()->selection()->setSelection(newSelection); - } -} - -VisiblePosition AccessibilityRenderObject::visiblePositionForPoint(const IntPoint& point) const -{ - // convert absolute point to view coordinates - FrameView* frameView = m_renderer->document()->topDocument()->renderer()->view()->frameView(); - RenderObject* renderer = topRenderer(); - Node* innerNode = 0; - - // locate the node containing the point - IntPoint pointResult; - while (1) { - IntPoint ourpoint; -#if PLATFORM(MAC) - ourpoint = frameView->screenToContents(point); -#else - ourpoint = point; -#endif - HitTestRequest request(true, true); - HitTestResult result(ourpoint); - renderer->layer()->hitTest(request, result); - innerNode = result.innerNode(); - if (!innerNode || !innerNode->renderer()) - return VisiblePosition(); - - pointResult = result.localPoint(); - - // done if hit something other than a widget - renderer = innerNode->renderer(); - if (!renderer->isWidget()) - break; - - // descend into widget (FRAME, IFRAME, OBJECT...) - Widget* widget = static_cast<RenderWidget*>(renderer)->widget(); - if (!widget || !widget->isFrameView()) - break; - Frame* frame = static_cast<FrameView*>(widget)->frame(); - if (!frame) - break; - Document* document = frame->document(); - if (!document) - break; - renderer = document->renderer(); - frameView = static_cast<FrameView*>(widget); - } - - return innerNode->renderer()->positionForPoint(pointResult); -} - -// NOTE: Consider providing this utility method as AX API -VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(unsigned indexValue, bool lastIndexOK) const -{ - if (!isTextControl()) - return VisiblePosition(); - - // lastIndexOK specifies whether the position after the last character is acceptable - if (indexValue >= text().length()) { - if (!lastIndexOK || indexValue > text().length()) - return VisiblePosition(); - } - VisiblePosition position = visiblePositionForIndex(indexValue); - position.setAffinity(DOWNSTREAM); - return position; -} - -// NOTE: Consider providing this utility method as AX API -int AccessibilityRenderObject::index(const VisiblePosition& position) const -{ - if (!isTextControl()) - return -1; - - Node* node = position.deepEquivalent().node(); - if (!node) - return -1; - - for (RenderObject* renderer = node->renderer(); renderer && renderer->element(); renderer = renderer->parent()) { - if (renderer == m_renderer) - return indexForVisiblePosition(position); - } - - return -1; -} - -// Given a line number, the range of characters of the text associated with this accessibility -// object that contains the line number. -PlainTextRange AccessibilityRenderObject::doAXRangeForLine(unsigned lineNumber) const -{ - if (!isTextControl()) - return PlainTextRange(); - - // iterate to the specified line - VisiblePosition visiblePos = visiblePositionForIndex(0); - VisiblePosition savedVisiblePos; - for (unsigned lineCount = lineNumber; lineCount != 0; lineCount -= 1) { - savedVisiblePos = visiblePos; - visiblePos = nextLinePosition(visiblePos, 0); - if (visiblePos.isNull() || visiblePos == savedVisiblePos) - return PlainTextRange(); - } - - // make a caret selection for the marker position, then extend it to the line - // NOTE: ignores results of selection.modify because it returns false when - // starting at an empty line. The resulting selection in that case - // will be a caret at visiblePos. - SelectionController selection; - selection.setSelection(Selection(visiblePos)); - selection.modify(SelectionController::EXTEND, SelectionController::LEFT, LineBoundary); - selection.modify(SelectionController::EXTEND, SelectionController::RIGHT, LineBoundary); - - // calculate the indices for the selection start and end - VisiblePosition startPosition = selection.selection().visibleStart(); - VisiblePosition endPosition = selection.selection().visibleEnd(); - int index1 = indexForVisiblePosition(startPosition); - int index2 = indexForVisiblePosition(endPosition); - - // add one to the end index for a line break not caused by soft line wrap (to match AppKit) - if (endPosition.affinity() == DOWNSTREAM && endPosition.next().isNotNull()) - index2 += 1; - - // return nil rather than an zero-length range (to match AppKit) - if (index1 == index2) - return PlainTextRange(); - - return PlainTextRange(index1, index2 - index1); -} - -// The composed character range in the text associated with this accessibility object that -// is specified by the given index value. This parameterized attribute returns the complete -// range of characters (including surrogate pairs of multi-byte glyphs) at the given index. -PlainTextRange AccessibilityRenderObject::doAXRangeForIndex(unsigned index) const -{ - if (!isTextControl()) - return PlainTextRange(); - - String elementText = text(); - if (!elementText.length() || index > elementText.length() - 1) - return PlainTextRange(); - - return PlainTextRange(index, 1); -} - -// A substring of the text associated with this accessibility object that is -// specified by the given character range. -String AccessibilityRenderObject::doAXStringForRange(const PlainTextRange& range) const -{ - if (isPasswordField()) - return String(); - - if (range.length == 0) - return ""; - - if (!isTextControl()) - return String(); - - String elementText = text(); - if (range.start + range.length > elementText.length()) - return String(); - - return elementText.substring(range.start, range.length); -} - -// The bounding rectangle of the text associated with this accessibility object that is -// specified by the given range. This is the bounding rectangle a sighted user would see -// on the display screen, in pixels. -IntRect AccessibilityRenderObject::doAXBoundsForRange(const PlainTextRange& range) const -{ - if (isTextControl()) - return boundsForVisiblePositionRange(visiblePositionRangeForRange(range)); - return IntRect(); -} - -AccessibilityObject* AccessibilityRenderObject::doAccessibilityHitTest(const IntPoint& point) const -{ - if (!m_renderer) - return 0; - - RenderLayer* layer = m_renderer->layer(); - if (!layer) - return 0; - - HitTestRequest request(true, true); - HitTestResult hitTestResult = HitTestResult(point); - layer->hitTest(request, hitTestResult); - if (!hitTestResult.innerNode()) - return 0; - Node* node = hitTestResult.innerNode()->shadowAncestorNode(); - RenderObject* obj = node->renderer(); - if (!obj) - return 0; - - AccessibilityObject *result = obj->document()->axObjectCache()->get(obj); - - if (obj->isListBox()) - return static_cast<AccessibilityListBox*>(result)->doAccessibilityHitTest(point); - - if (result->accessibilityIsIgnored()) - result = result->parentObjectUnignored(); - - return result; -} - -AccessibilityObject* AccessibilityRenderObject::focusedUIElement() const -{ - // get the focused node in the page - Page* page = m_renderer->document()->page(); - if (!page) - return 0; - - Document* focusedDocument = page->focusController()->focusedOrMainFrame()->document(); - Node* focusedNode = focusedDocument->focusedNode(); - if (!focusedNode) - focusedNode = focusedDocument; - - RenderObject* focusedNodeRenderer = focusedNode->renderer(); - if (!focusedNodeRenderer) - return 0; - - AccessibilityObject* obj = focusedNodeRenderer->document()->axObjectCache()->get(focusedNodeRenderer); - - if (obj->shouldFocusActiveDescendant()) { - if (AccessibilityObject* descendant = obj->activeDescendant()) - obj = descendant; - } - - // the HTML element, for example, is focusable but has an AX object that is ignored - if (obj->accessibilityIsIgnored()) - obj = obj->parentObjectUnignored(); - - return obj; -} - -bool AccessibilityRenderObject::shouldFocusActiveDescendant() const -{ - switch (ariaRoleAttribute()) { - case GroupRole: - case ComboBoxRole: - case ListBoxRole: - case MenuRole: - case MenuBarRole: - case RadioGroupRole: - case RowRole: - case PopUpButtonRole: - case ProgressIndicatorRole: - case ToolbarRole: - case OutlineRole: - /* FIXME: replace these with actual roles when they are added to AccessibilityRole - composite - alert - alertdialog - grid - status - timer - tree - */ - return true; - default: - return false; - } -} - -AccessibilityObject* AccessibilityRenderObject::activeDescendant() const -{ - if (renderer()->element() && !renderer()->element()->isElementNode()) - return 0; - Element* element = static_cast<Element*>(renderer()->element()); - - String activeDescendantAttrStr = element->getAttribute(aria_activedescendantAttr).string(); - if (activeDescendantAttrStr.isNull() || activeDescendantAttrStr.isEmpty()) - return 0; - - Element* target = renderer()->document()->getElementById(activeDescendantAttrStr); - if (!target) - return 0; - - AccessibilityObject* obj = renderer()->document()->axObjectCache()->get(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; - return 0; -} - - -void AccessibilityRenderObject::handleActiveDescendantChanged() -{ - Element* element = static_cast<Element*>(renderer()->element()); - if (!element) - return; - Document* doc = renderer()->document(); - if (!doc->frame()->selection()->isFocusedAndActive() || doc->focusedNode() != element) - return; - AccessibilityRenderObject* activedescendant = static_cast<AccessibilityRenderObject*>(activeDescendant()); - - if (activedescendant && shouldFocusActiveDescendant()) - doc->axObjectCache()->postNotificationToElement(activedescendant->renderer(), "AXFocusedUIElementChanged"); -} - - -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); - } - - return 0; -} - -typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap; - -static const ARIARoleMap& createARIARoleMap() -{ - struct RoleEntry { - String ariaRole; - AccessibilityRole webcoreRole; - }; - - const RoleEntry roles[] = { - { "button", ButtonRole }, - { "checkbox", CheckBoxRole }, - { "group", GroupRole }, - { "heading", HeadingRole }, - { "img", ImageRole }, - { "link", WebCoreLinkRole }, - { "listbox", ListBoxRole }, - // "option" isn't here because it may map to different roles depending on the parent element's role - { "menu", MenuRole }, - { "menubar", GroupRole }, - // "menuitem" isn't here because it may map to different roles depending on the parent element's role - { "menuitemcheckbox", MenuItemRole }, - { "menuitemradio", MenuItemRole }, - { "progressbar", ProgressIndicatorRole }, - { "radio", RadioButtonRole }, - { "range", SliderRole }, - { "slider", SliderRole }, - { "spinbutton", ProgressIndicatorRole }, - { "textbox", TextAreaRole } - }; - ARIARoleMap& roleMap = *new ARIARoleMap; - - const unsigned numRoles = sizeof(roles) / sizeof(roles[0]); - for (unsigned i = 0; i < numRoles; ++i) - roleMap.set(roles[i].ariaRole, roles[i].webcoreRole); - return roleMap; -} - -static AccessibilityRole ariaRoleToWebCoreRole(String value) -{ - ASSERT(!value.isEmpty() && !value.isNull()); - static const ARIARoleMap& roleMap = createARIARoleMap(); - return roleMap.get(value); -} - -AccessibilityRole AccessibilityRenderObject::determineAriaRoleAttribute() const -{ - String ariaRole = getAttribute(roleAttr).string(); - if (ariaRole.isNull() || ariaRole.isEmpty()) - return UnknownRole; - - AccessibilityRole role = ariaRoleToWebCoreRole(ariaRole); - if (role) - return role; - // selects and listboxes both have options as child roles, but they map to different roles within WebCore - if (equalIgnoringCase(ariaRole,"option")) { - if (parentObjectUnignored()->ariaRoleAttribute() == MenuRole) - return MenuItemRole; - if (parentObjectUnignored()->ariaRoleAttribute() == ListBoxRole) - return ListBoxOptionRole; - } - // an aria "menuitem" may map to MenuButton or MenuItem depending on its parent - if (equalIgnoringCase(ariaRole,"menuitem")) { - if (parentObjectUnignored()->ariaRoleAttribute() == GroupRole) - return MenuButtonRole; - if (parentObjectUnignored()->ariaRoleAttribute() == MenuRole) - return MenuItemRole; - } - - return UnknownRole; -} - -void AccessibilityRenderObject::setAriaRole() -{ - m_ariaRole = determineAriaRoleAttribute(); -} - -AccessibilityRole AccessibilityRenderObject::ariaRoleAttribute() const -{ - return m_ariaRole; -} - -AccessibilityRole AccessibilityRenderObject::roleValue() const -{ - if (!m_renderer) - return UnknownRole; - - Node* node = m_renderer->element(); - AccessibilityRole ariaRole = ariaRoleAttribute(); - if (ariaRole != UnknownRole) - return ariaRole; - - if (node && node->isLink()) { - if (m_renderer->isImage()) - return ImageMapRole; - return WebCoreLinkRole; - } - if (m_renderer->isListMarker()) - return ListMarkerRole; - if (node && node->hasTagName(buttonTag)) - return ButtonRole; - if (m_renderer->isText()) - return StaticTextRole; - if (m_renderer->isImage()) { - if (node && node->hasTagName(inputTag)) - return ButtonRole; - return ImageRole; - } - if (m_renderer->isRenderView()) - return WebAreaRole; - - if (m_renderer->isTextField()) - return TextFieldRole; - - if (m_renderer->isTextArea()) - return TextAreaRole; - - if (node && node->hasTagName(inputTag)) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(node); - if (input->inputType() == HTMLInputElement::CHECKBOX) - return CheckBoxRole; - if (input->inputType() == HTMLInputElement::RADIO) - return RadioButtonRole; - if (input->isTextButton()) - return ButtonRole; - } - - if (node && node->hasTagName(buttonTag)) - return ButtonRole; - - if (isFileUploadButton()) - return ButtonRole; - - if (m_renderer->isMenuList()) - return PopUpButtonRole; - - if (headingLevel(m_renderer->element()) != 0) - return HeadingRole; - - if (node && node->hasTagName(ddTag)) - return DefinitionListDefinitionRole; - - if (node && node->hasTagName(dtTag)) - return DefinitionListTermRole; - - if (m_renderer->isBlockFlow() || (node && node->hasTagName(labelTag))) - return GroupRole; - - return UnknownRole; -} - -bool AccessibilityRenderObject::isPresentationalChildOfAriaRole() const -{ - // Walk the parent chain looking for a parent that has presentational children - AccessibilityObject* parent; - for (parent = parentObject(); parent && !parent->ariaRoleHasPresentationalChildren(); parent = parent->parentObject()) - ; - return parent; -} - -bool AccessibilityRenderObject::ariaRoleHasPresentationalChildren() const -{ - switch (m_ariaRole) { - case ButtonRole: - case SliderRole: - case ImageRole: - case ProgressIndicatorRole: - //case SeparatorRole: - return true; - default: - return false; - } -} - -bool AccessibilityRenderObject::canSetFocusAttribute() const -{ - // 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()) - return false; - - switch (roleValue()) { - case WebCoreLinkRole: - case ImageMapLinkRole: - case TextFieldRole: - case TextAreaRole: - case ButtonRole: - case PopUpButtonRole: - case CheckBoxRole: - case RadioButtonRole: - return true; - default: - return false; - } -} - -bool AccessibilityRenderObject::canSetValueAttribute() const -{ - if (isWebArea()) - return !isReadOnly(); - - return isTextControl() || isProgressIndicator() || isSlider(); -} - -bool AccessibilityRenderObject::canSetTextRangeAttributes() const -{ - return isTextControl(); -} - -void AccessibilityRenderObject::childrenChanged() -{ - clearChildren(); - - if (accessibilityIsIgnored()) { - AccessibilityObject* parent = parentObject(); - if (parent) - parent->childrenChanged(); - } -} - -bool AccessibilityRenderObject::canHaveChildren() const -{ - if (!m_renderer) - return false; - - // Elements that should not have children - switch (roleValue()) { - case ImageRole: - case ButtonRole: - case PopUpButtonRole: - case CheckBoxRole: - case RadioButtonRole: - return false; - default: - return true; - } -} - -const AccessibilityObject::AccessibilityChildrenVector& AccessibilityRenderObject::children() -{ - if (!m_haveChildren) - addChildren(); - return m_children; -} - -void AccessibilityRenderObject::addChildren() -{ - // If the need to add more children in addition to existing children arises, - // childrenChanged should have been called, leaving the object with no children. - ASSERT(!m_haveChildren); - - // nothing to add if there is no RenderObject - if (!m_renderer) - return; - - m_haveChildren = true; - - if (!canHaveChildren()) - return; - - // add all unignored acc children - for (RefPtr<AccessibilityObject> obj = firstChild(); obj; obj = obj->nextSibling()) { - if (obj->accessibilityIsIgnored()) { - if (!obj->hasChildren()) - obj->addChildren(); - AccessibilityChildrenVector children = obj->children(); - unsigned length = children.size(); - for (unsigned i = 0; i < length; ++i) - m_children.append(children[i]); - } else - m_children.append(obj); - } - - // for a RenderImage, add the <area> elements as individual accessibility objects - if (m_renderer->isRenderImage()) { - HTMLMapElement* map = static_cast<RenderImage*>(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)); - areaObject->setHTMLAreaElement(static_cast<HTMLAreaElement*>(current)); - areaObject->setHTMLMapElement(map); - areaObject->setParent(this); - - m_children.append(areaObject); - } - } - } - } -} - -void AccessibilityRenderObject::ariaListboxSelectedChildren(AccessibilityChildrenVector& result) -{ - AccessibilityObject* child = firstChild(); - bool isMultiselectable = false; - - Element* element = static_cast<Element*>(renderer()->element()); - if (!element || !element->isElementNode()) // do this check to ensure safety of static_cast above - return; - - String multiselectablePropertyStr = element->getAttribute("aria-multiselectable").string(); - isMultiselectable = equalIgnoringCase(multiselectablePropertyStr, "true"); - - while (child) { - // every child should have aria-role option, and if so, check for selected attribute/state - AccessibilityRole ariaRole = child->ariaRoleAttribute(); - RenderObject* childRenderer = 0; - if (child->isAccessibilityRenderObject()) - childRenderer = static_cast<AccessibilityRenderObject*>(child)->renderer(); - if (childRenderer && ariaRole == ListBoxOptionRole) { - Element* childElement = static_cast<Element*>(childRenderer->element()); - 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")) { - result.append(child); - if (isMultiselectable) - return; - } - } - } - child = child->nextSibling(); - } -} - -void AccessibilityRenderObject::selectedChildren(AccessibilityChildrenVector& result) -{ - ASSERT(result.isEmpty()); - - // only listboxes should be asked for their selected children. - if (ariaRoleAttribute() != ListBoxRole) { // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes - ASSERT_NOT_REACHED(); - return; - } - return ariaListboxSelectedChildren(result); -} - -void AccessibilityRenderObject::ariaListboxVisibleChildren(AccessibilityChildrenVector& result) -{ - if (!hasChildren()) - addChildren(); - - unsigned length = m_children.size(); - for (unsigned i = 0; i < length; i++) { - if (!m_children[i]->isOffScreen()) - result.append(m_children[i]); - } -} - -void AccessibilityRenderObject::visibleChildren(AccessibilityChildrenVector& result) -{ - ASSERT(result.isEmpty()); - - // only listboxes are asked for their visible children. - if (ariaRoleAttribute() != ListBoxRole) { // native list boxes would be AccessibilityListBoxes, so only check for aria list boxes - ASSERT_NOT_REACHED(); - return; - } - 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. - DEFINE_STATIC_LOCAL(const String, buttonAction, (AXButtonActionVerb())); - DEFINE_STATIC_LOCAL(const String, textFieldAction, (AXTextFieldActionVerb())); - DEFINE_STATIC_LOCAL(const String, radioButtonAction, (AXRadioButtonActionVerb())); - DEFINE_STATIC_LOCAL(const String, checkedCheckBoxAction, (AXCheckedCheckBoxActionVerb())); - DEFINE_STATIC_LOCAL(const String, uncheckedCheckBoxAction, (AXUncheckedCheckBoxActionVerb())); - DEFINE_STATIC_LOCAL(const String, linkAction, (AXLinkActionVerb())); - DEFINE_STATIC_LOCAL(const String, noAction, ()); - - switch (roleValue()) { - case ButtonRole: - return buttonAction; - case TextFieldRole: - case TextAreaRole: - return textFieldAction; - case RadioButtonRole: - return radioButtonAction; - case CheckBoxRole: - return isChecked() ? checkedCheckBoxAction : uncheckedCheckBoxAction; - case LinkRole: - case WebCoreLinkRole: - return linkAction; - default: - return noAction; - } -} - - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityRenderObject.h b/src/3rdparty/webkit/WebCore/page/AccessibilityRenderObject.h deleted file mode 100644 index 9d43ad8..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityRenderObject.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2008 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 AccessibilityRenderObject_h -#define AccessibilityRenderObject_h - -#include "AccessibilityObject.h" - -namespace WebCore { - -class AXObjectCache; -class Element; -class Frame; -class FrameView; -class HitTestResult; -class HTMLAnchorElement; -class HTMLAreaElement; -class HTMLElement; -class HTMLLabelElement; -class HTMLMapElement; -class HTMLSelectElement; -class IntPoint; -class IntSize; -class Node; -class RenderObject; -class RenderListBox; -class RenderTextControl; -class Selection; -class String; -class Widget; - -class AccessibilityRenderObject : public AccessibilityObject { -protected: - AccessibilityRenderObject(RenderObject*); -public: - static PassRefPtr<AccessibilityRenderObject> create(RenderObject*); - virtual ~AccessibilityRenderObject(); - - bool isAccessibilityRenderObject() const { return true; }; - - virtual bool isAnchor() const; - virtual bool isAttachment() const; - virtual bool isHeading() const; - virtual bool isLink() const; - virtual bool isImageButton() const; - virtual bool isImage() const; - virtual bool isNativeImage() const; - virtual bool isPasswordField() const; - virtual bool isTextControl() const; - virtual bool isNativeTextControl() const; - virtual bool isWebArea() const; - virtual bool isCheckboxOrRadio() const; - virtual bool isFileUploadButton() const; - virtual bool isProgressIndicator() const; - virtual bool isSlider() const; - virtual bool isMenuRelated() const; - virtual bool isMenu() const; - virtual bool isMenuBar() const; - virtual bool isMenuButton() const; - virtual bool isMenuItem() const; - virtual bool isControl() const; - virtual bool isFieldset() const; - virtual bool isGroup() const; - - virtual bool isEnabled() const; - virtual bool isSelected() const; - virtual bool isFocused() const; - virtual bool isChecked() const; - virtual bool isHovered() const; - virtual bool isIndeterminate() const; - virtual bool isLoaded() const; - virtual bool isMultiSelect() const; - virtual bool isOffScreen() const; - virtual bool isPressed() const; - virtual bool isReadOnly() const; - virtual bool isVisited() const; - - const AtomicString& getAttribute(const QualifiedName&) const; - virtual bool canSetFocusAttribute() const; - virtual bool canSetTextRangeAttributes() const; - virtual bool canSetValueAttribute() const; - - virtual bool hasIntValue() const; - - virtual bool accessibilityIsIgnored() const; - - static int headingLevel(Node*); - virtual int intValue() const; - virtual float valueForRange() const; - virtual float maxValueForRange() const; - virtual float minValueForRange() const; - virtual int layoutCount() const; - - virtual AccessibilityObject* doAccessibilityHitTest(const IntPoint&) const; - virtual AccessibilityObject* focusedUIElement() const; - virtual AccessibilityObject* firstChild() const; - virtual AccessibilityObject* lastChild() const; - virtual AccessibilityObject* previousSibling() const; - virtual AccessibilityObject* nextSibling() const; - virtual AccessibilityObject* parentObject() const; - virtual AccessibilityObject* observableObject() const; - virtual void linkedUIElements(AccessibilityChildrenVector&) const; - virtual AccessibilityObject* titleUIElement() const; - virtual AccessibilityRole ariaRoleAttribute() const; - virtual bool isPresentationalChildOfAriaRole() const; - virtual bool ariaRoleHasPresentationalChildren() const; - void setAriaRole(); - virtual AccessibilityRole roleValue() const; - virtual AXObjectCache* axObjectCache() const; - - virtual Element* actionElement() const; - Element* mouseButtonListener() const; - FrameView* frameViewIfRenderView() const; - virtual Element* anchorElement() const; - AccessibilityObject* menuForMenuButton() const; - AccessibilityObject* menuButtonForMenu() const; - - virtual IntRect boundingBoxRect() const; - virtual IntRect elementRect() const; - virtual IntSize size() const; - - void setRenderer(RenderObject* renderer) { m_renderer = renderer; } - RenderObject* renderer() const { return m_renderer; } - RenderObject* topRenderer() const; - RenderTextControl* textControl() const; - Document* document() const; - FrameView* topDocumentFrameView() const; - HTMLLabelElement* labelElementContainer() const; - - virtual KURL url() const; - virtual PlainTextRange selectedTextRange() const; - virtual Selection selection() const; - virtual String stringValue() const; - virtual String ariaAccessiblityName(const String&) const; - virtual String ariaLabeledByAttribute() const; - virtual String title() const; - virtual String ariaDescribedByAttribute() const; - virtual String accessibilityDescription() const; - virtual String helpText() const; - virtual String textUnderElement() const; - virtual String text() const; - virtual int textLength() const; - virtual PassRefPtr<Range> ariaSelectedTextDOMRange() const; - virtual String selectedText() const; - virtual const AtomicString& accessKey() const; - virtual const String& actionVerb() const; - virtual Widget* widget() const; - virtual Widget* widgetForAttachmentView() const; - virtual void getDocumentLinks(AccessibilityChildrenVector&); - virtual FrameView* documentFrameView() const; - - virtual const AccessibilityChildrenVector& children(); - - virtual void setFocused(bool); - virtual void setSelectedTextRange(const PlainTextRange&); - virtual void setValue(const String&); - - virtual void detach(); - virtual void childrenChanged(); - virtual void addChildren(); - virtual bool canHaveChildren() const; - virtual void selectedChildren(AccessibilityChildrenVector&); - virtual void visibleChildren(AccessibilityChildrenVector&); - virtual bool shouldFocusActiveDescendant() const; - virtual AccessibilityObject* activeDescendant() const; - virtual void handleActiveDescendantChanged(); - - virtual VisiblePositionRange visiblePositionRange() const; - virtual VisiblePositionRange visiblePositionRangeForLine(unsigned) const; - virtual IntRect boundsForVisiblePositionRange(const VisiblePositionRange&) const; - virtual void setSelectedVisiblePositionRange(const VisiblePositionRange&) const; - - virtual VisiblePosition visiblePositionForPoint(const IntPoint&) const; - virtual VisiblePosition visiblePositionForIndex(unsigned indexValue, bool lastIndexOK) const; - virtual int index(const VisiblePosition&) const; - - virtual VisiblePosition visiblePositionForIndex(int) const; - virtual int indexForVisiblePosition(const VisiblePosition&) const; - - virtual PlainTextRange doAXRangeForLine(unsigned) const; - virtual PlainTextRange doAXRangeForIndex(unsigned) const; - - virtual String doAXStringForRange(const PlainTextRange&) const; - virtual IntRect doAXBoundsForRange(const PlainTextRange&) const; - -protected: - RenderObject* m_renderer; - AccessibilityRole m_ariaRole; - - void setRenderObject(RenderObject* renderer) { m_renderer = renderer; } - virtual void removeAXObjectID(); - - virtual bool isDetached() const { return !m_renderer; } - -private: - void ariaListboxSelectedChildren(AccessibilityChildrenVector&); - void ariaListboxVisibleChildren(AccessibilityChildrenVector&); - - Element* menuElementForMenuButton() const; - Element* menuItemElementForMenu() const; - AccessibilityRole determineAriaRoleAttribute() const; - - IntRect checkboxOrRadioRect() const; - void addRadioButtonGroupMembers(AccessibilityChildrenVector& linkedUIElements) const; - AccessibilityObject* internalLinkElement() const; - AccessibilityObject* accessibilityParentForImageMap(HTMLMapElement* map) const; - -}; - -} // namespace WebCore - -#endif // AccessibilityRenderObject_h diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTable.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityTable.cpp deleted file mode 100644 index ee54496..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTable.cpp +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AccessibilityTable.h" - -#include "AccessibilityTableCell.h" -#include "AccessibilityTableColumn.h" -#include "AccessibilityTableHeaderContainer.h" -#include "AccessibilityTableRow.h" -#include "AXObjectCache.h" -#include "HTMLNames.h" -#include "HTMLTableElement.h" -#include "HTMLTableCaptionElement.h" -#include "HTMLTableCellElement.h" -#include "RenderObject.h" -#include "RenderTable.h" -#include "RenderTableCell.h" -#include "RenderTableSection.h" - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityTable::AccessibilityTable(RenderObject* renderer) - : AccessibilityRenderObject(renderer), - m_headerContainer(0) -{ - // FIXME: We need to disable Accessibility Tables entirely on the Mac until <rdar://problem/6372481> is resolved. -#if PLATFORM(MAC) - m_isAccessibilityTable = false; -#else - m_isAccessibilityTable = isTableExposableThroughAccessibility(); -#endif - -} - -AccessibilityTable::~AccessibilityTable() -{ -} - -PassRefPtr<AccessibilityTable> AccessibilityTable::create(RenderObject* renderer) -{ - return adoptRef(new AccessibilityTable(renderer)); -} - -bool AccessibilityTable::isTableExposableThroughAccessibility() -{ - // the following is a heuristic used to determine if a - // <table> should be exposed as an AXTable. The goal - // is to only show "data" tables - - if (!m_renderer || !m_renderer->isTable()) - return false; - - // if the developer assigned an aria role to this, then we shouldn't - // expose it as a table, unless, of course, the aria role is a table - AccessibilityRole ariaRole = ariaRoleAttribute(); - if (ariaRole == TableRole) - return true; - if (ariaRole != UnknownRole) - return false; - - RenderTable* table = static_cast<RenderTable*>(m_renderer); - - // this employs a heuristic to determine if this table should appear. - // Only "data" tables should be exposed as tables. - // Unfortunately, there is no good way to determine the difference - // between a "layout" table and a "data" table - - Node* tableNode = table->element(); - if (!tableNode || !tableNode->hasTagName(tableTag)) - return false; - - // if there is a caption element, summary, THEAD, or TFOOT section, it's most certainly a data table - HTMLTableElement* tableElement = static_cast<HTMLTableElement*>(tableNode); - if (!tableElement->summary().isEmpty() || tableElement->tHead() || tableElement->tFoot() || tableElement->caption()) - return true; - - // if someone used "rules" attribute than the table should appear - if (!tableElement->rules().isEmpty()) - return true; - - // go through the cell's and check for tell-tale signs of "data" table status - // cells have borders, or use attributes like headers, abbr, scope or axis - RenderTableSection* firstBody = table->firstBody(); - if (!firstBody) - return false; - - int numCols = firstBody->numColumns(); - int numRows = firstBody->numRows(); - - // if there's only one cell, it's not a good AXTable candidate - if (numRows == 1 && numCols == 1) - return false; - - // store the background color of the table to check against cell's background colors - RenderStyle* tableStyle = table->style(); - if (!tableStyle) - return false; - Color tableBGColor = tableStyle->backgroundColor(); - - // check enough of the cells to find if the table matches our criteria - // Criteria: - // 1) must have at least one valid cell (and) - // 2) at least half of cells have borders (or) - // 3) at least half of cells have different bg colors than the table, and there is cell spacing - unsigned validCellCount = 0; - unsigned borderedCellCount = 0; - unsigned backgroundDifferenceCellCount = 0; - - for (int row = 0; row < numRows; ++row) { - for (int col = 0; col < numCols; ++col) { - RenderTableCell* cell = firstBody->cellAt(row, col).cell; - if (!cell) - continue; - Node* cellNode = cell->element(); - if (!cellNode) - continue; - - if (cell->width() < 1 || cell->height() < 1) - continue; - - validCellCount++; - - HTMLTableCellElement* cellElement = static_cast<HTMLTableCellElement*>(cellNode); - - // in this case, the developer explicitly assigned a "data" table attribute - if (!cellElement->headers().isEmpty() || !cellElement->abbr().isEmpty() || - !cellElement->axis().isEmpty() || !cellElement->scope().isEmpty()) - return true; - - RenderStyle* renderStyle = cell->style(); - if (!renderStyle) - continue; - - // a cell needs to have matching bordered sides, before it can be considered a bordered cell. - if ((cell->borderTop() > 0 && cell->borderBottom() > 0) || - (cell->borderLeft() > 0 && cell->borderRight() > 0)) - borderedCellCount++; - - // if the cell has a different color from the table and there is cell spacing, - // then it is probably a data table cell (spacing and colors take the place of borders) - Color cellColor = renderStyle->backgroundColor(); - if (table->hBorderSpacing() > 0 && table->vBorderSpacing() > 0 && - tableBGColor != cellColor && cellColor.alpha() != 1) - backgroundDifferenceCellCount++; - - // if we've found 10 "good" cells, we don't need to keep searching - if (borderedCellCount >= 10 || backgroundDifferenceCellCount >= 10) - return true; - } - } - - // if there is less than two valid cells, it's not a data table - if (validCellCount <= 1) - return false; - - // half of the cells had borders, it's a data table - unsigned neededCellCount = validCellCount / 2; - if (borderedCellCount >= neededCellCount) - return true; - - // half had different background colors, it's a data table - if (backgroundDifferenceCellCount >= neededCellCount) - return true; - - return false; -} - -void AccessibilityTable::clearChildren() -{ - m_children.clear(); - m_rows.clear(); - m_columns.clear(); - m_haveChildren = false; -} - -void AccessibilityTable::addChildren() -{ - if (!isDataTable()) { - AccessibilityRenderObject::addChildren(); - return; - } - - ASSERT(!m_haveChildren); - - m_haveChildren = true; - if (!m_renderer) - return; - - RenderTable* table = static_cast<RenderTable*>(m_renderer); - AXObjectCache* axCache = m_renderer->document()->axObjectCache(); - - // go through all the available sections to pull out the rows - // and add them as children - RenderTableSection* tableSection = table->header(); - if (!tableSection) - tableSection = table->firstBody(); - - if (!tableSection) - return; - - RenderTableSection* initialTableSection = tableSection; - - while (tableSection) { - - HashSet<AccessibilityObject*> appendedRows; - - unsigned numRows = tableSection->numRows(); - unsigned numCols = tableSection->numColumns(); - for (unsigned rowIndex = 0; rowIndex < numRows; ++rowIndex) { - for (unsigned colIndex = 0; colIndex < numCols; ++colIndex) { - - RenderTableCell* cell = tableSection->cellAt(rowIndex, colIndex).cell; - if (!cell) - continue; - - AccessibilityObject* rowObject = axCache->get(cell->parent()); - if (!rowObject->isTableRow()) - continue; - - AccessibilityTableRow* row = static_cast<AccessibilityTableRow*>(rowObject); - // we need to check every cell for a new row, because cell spans - // can cause us to mess rows if we just check the first column - if (appendedRows.contains(row)) - continue; - - row->setRowIndex((int)m_rows.size()); - m_rows.append(row); - m_children.append(row); - appendedRows.add(row); - } - } - - tableSection = table->sectionBelow(tableSection, true); - } - - // 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)); - column->setColumnIndex((int)i); - column->setParentTable(this); - m_columns.append(column); - m_children.append(column); - } - - AccessibilityObject* headerContainerObject = headerContainer(); - if (headerContainerObject) - m_children.append(headerContainerObject); -} - -AccessibilityObject* AccessibilityTable::headerContainer() -{ - if (m_headerContainer) - return m_headerContainer; - - m_headerContainer = static_cast<AccessibilityTableHeaderContainer*>(axObjectCache()->get(TableHeaderContainerRole)); - m_headerContainer->setParentTable(this); - - return m_headerContainer; -} - -AccessibilityObject::AccessibilityChildrenVector& AccessibilityTable::columns() -{ - if (!hasChildren()) - addChildren(); - - return m_columns; -} - -AccessibilityObject::AccessibilityChildrenVector& AccessibilityTable::rows() -{ - if (!hasChildren()) - addChildren(); - - return m_rows; -} - -void AccessibilityTable::rowHeaders(AccessibilityChildrenVector& headers) -{ - if (!m_renderer) - return; - - if (!hasChildren()) - addChildren(); - - unsigned rowCount = m_rows.size(); - for (unsigned k = 0; k < rowCount; ++k) { - AccessibilityObject* header = static_cast<AccessibilityTableRow*>(m_rows[k].get())->headerObject(); - if (!header) - continue; - headers.append(header); - } -} - -void AccessibilityTable::columnHeaders(AccessibilityChildrenVector& headers) -{ - if (!m_renderer) - return; - - if (!hasChildren()) - addChildren(); - - unsigned colCount = m_columns.size(); - for (unsigned k = 0; k < colCount; ++k) { - AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_columns[k].get())->headerObject(); - if (!header) - continue; - headers.append(header); - } -} - -void AccessibilityTable::cells(AccessibilityObject::AccessibilityChildrenVector& cells) -{ - if (!m_renderer) - return; - - if (!hasChildren()) - addChildren(); - - int numRows = m_rows.size(); - for (int row = 0; row < numRows; ++row) { - AccessibilityChildrenVector rowChildren = m_rows[row]->children(); - cells.append(rowChildren); - } -} - -const unsigned AccessibilityTable::columnCount() -{ - if (!hasChildren()) - addChildren(); - - return m_columns.size(); -} - -const unsigned AccessibilityTable::rowCount() -{ - if (!hasChildren()) - addChildren(); - - return m_rows.size(); -} - -AccessibilityTableCell* AccessibilityTable::cellForColumnAndRow(unsigned column, unsigned row) -{ - if (!m_renderer) - return 0; - - if (!hasChildren()) - addChildren(); - - RenderTable* table = static_cast<RenderTable*>(m_renderer); - RenderTableSection* tableSection = table->header(); - if (!tableSection) - tableSection = table->firstBody(); - - RenderTableCell* cell = 0; - unsigned rowCount = 0; - unsigned rowOffset = 0; - while (tableSection) { - - rowCount += tableSection->numRows(); - unsigned numCols = tableSection->numColumns(); - - if (row < rowCount && column < numCols) { - int sectionSpecificRow = row - rowOffset; - cell = tableSection->cellAt(sectionSpecificRow, column).cell; - - // we didn't find the cell, which means there's spanning happening - // search backwards to find the spanning cell - if (!cell) { - - // first try rows - for (int testRow = sectionSpecificRow-1; testRow >= 0; --testRow) { - cell = tableSection->cellAt(testRow, column).cell; - // cell overlapped. use this one - if (cell && ((cell->row() + (cell->rowSpan()-1)) >= (int)sectionSpecificRow)) - break; - cell = 0; - } - - if (!cell) { - // try cols - for (int testCol = column-1; testCol >= 0; --testCol) { - cell = tableSection->cellAt(sectionSpecificRow, testCol).cell; - // cell overlapped. use this one - if (cell && ((cell->col() + (cell->colSpan()-1)) >= (int)column)) - break; - cell = 0; - } - } - } - } - - if (cell) - break; - - rowOffset += rowCount; - // we didn't find anything between the rows we should have - if (row < rowOffset) - break; - tableSection = table->sectionBelow(tableSection, true); - } - - if (!cell) - return 0; - - AccessibilityObject* cellObject = axObjectCache()->get(cell); - ASSERT(cellObject->isTableCell()); - - return static_cast<AccessibilityTableCell*>(cellObject); -} - -AccessibilityRole AccessibilityTable::roleValue() const -{ - if (!isDataTable()) - return AccessibilityRenderObject::roleValue(); - - return TableRole; -} - -bool AccessibilityTable::accessibilityIsIgnored() const -{ - if (!isDataTable()) - return AccessibilityRenderObject::accessibilityIsIgnored(); - - return false; -} - -String AccessibilityTable::title() const -{ - if (!isDataTable()) - return AccessibilityRenderObject::title(); - - String title; - if (!m_renderer) - return title; - - // see if there is a caption - Node *tableElement = m_renderer->element(); - if (tableElement) { - HTMLTableCaptionElement* caption = static_cast<HTMLTableElement*>(tableElement)->caption(); - if (caption) - title = caption->innerText(); - } - - // try the standard - if (title.isEmpty()) - title = AccessibilityRenderObject::title(); - - return title; -} - -bool AccessibilityTable::isDataTable() const -{ - if (!m_renderer) - return false; - - return m_isAccessibilityTable; -} - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTable.h b/src/3rdparty/webkit/WebCore/page/AccessibilityTable.h deleted file mode 100644 index b98b6b7..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTable.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2008 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 AccessibilityTable_h -#define AccessibilityTable_h - -#include "AccessibilityRenderObject.h" - -namespace WebCore { - -class String; -class AccessibilityTableCell; -class AccessibilityTableHeaderContainer; - -class AccessibilityTable : public AccessibilityRenderObject { - -private: - AccessibilityTable(RenderObject*); -public: - static PassRefPtr<AccessibilityTable> create(RenderObject*); - virtual ~AccessibilityTable(); - - virtual bool isDataTable() const; - virtual AccessibilityRole roleValue() const; - - virtual bool accessibilityIsIgnored() const; - - virtual void addChildren(); - virtual void clearChildren(); - - AccessibilityChildrenVector& columns(); - AccessibilityChildrenVector& rows(); - - const unsigned columnCount(); - const unsigned rowCount(); - - virtual String title() const; - - // all the cells in the table - void cells(AccessibilityChildrenVector&); - AccessibilityTableCell* cellForColumnAndRow(unsigned column, unsigned row); - - void columnHeaders(AccessibilityChildrenVector&); - void rowHeaders(AccessibilityChildrenVector&); - - // an object that contains, as children, all the objects that act as headers - AccessibilityObject* headerContainer(); - -private: - AccessibilityChildrenVector m_rows; - AccessibilityChildrenVector m_columns; - - AccessibilityTableHeaderContainer* m_headerContainer; - mutable bool m_isAccessibilityTable; - - bool isTableExposableThroughAccessibility(); -}; - -} // namespace WebCore - -#endif // AccessibilityTable_h diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTableCell.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityTableCell.cpp deleted file mode 100644 index ff82811..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTableCell.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AccessibilityTableCell.h" - -#include "AXObjectCache.h" -#include "HTMLNames.h" -#include "RenderObject.h" -#include "RenderTableCell.h" - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityTableCell::AccessibilityTableCell(RenderObject* renderer) - : AccessibilityRenderObject(renderer) -{ -} - -AccessibilityTableCell::~AccessibilityTableCell() -{ -} - -PassRefPtr<AccessibilityTableCell> AccessibilityTableCell::create(RenderObject* renderer) -{ - return adoptRef(new AccessibilityTableCell(renderer)); -} - -bool AccessibilityTableCell::accessibilityIsIgnored() const -{ - if (!isTableCell()) - return AccessibilityRenderObject::accessibilityIsIgnored(); - - return false; -} - -bool AccessibilityTableCell::isTableCell() const -{ - if (!m_renderer) - return false; - - AccessibilityObject* renderTable = axObjectCache()->get(static_cast<RenderTableCell*>(m_renderer)->table()); - if (!renderTable->isDataTable()) - return false; - - return true; -} - -AccessibilityRole AccessibilityTableCell::roleValue() const -{ - if (!isTableCell()) - return AccessibilityRenderObject::roleValue(); - - return CellRole; -} - -void AccessibilityTableCell::rowIndexRange(pair<int, int>& rowRange) -{ - if (!m_renderer) - return; - - RenderTableCell* renderCell = static_cast<RenderTableCell*>(m_renderer); - rowRange.first = renderCell->row(); - rowRange.second = renderCell->rowSpan(); - - // since our table might have multiple sections, we have to offset our row appropriately - RenderTableSection* section = renderCell->section(); - RenderTable* table = renderCell->table(); - if (!table || !section) - return; - - RenderTableSection* tableSection = table->header(); - if (!tableSection) - tableSection = table->firstBody(); - - unsigned rowOffset = 0; - while (tableSection) { - if (tableSection == section) - break; - rowOffset += tableSection->numRows(); - tableSection = table->sectionBelow(tableSection, true); - } - - rowRange.first += rowOffset; -} - -void AccessibilityTableCell::columnIndexRange(pair<int, int>& columnRange) -{ - if (!m_renderer) - return; - - RenderTableCell* renderCell = static_cast<RenderTableCell*>(m_renderer); - columnRange.first = renderCell->col(); - columnRange.second = renderCell->colSpan(); -} - -AccessibilityObject* AccessibilityTableCell::titleUIElement() const -{ - // Try to find if the first cell in this row is a <th>. If it is, - // then it can act as the title ui element. (This is only in the - // case when the table is not appearing as an AXTable.) - if (!m_renderer || isTableCell()) - return 0; - - RenderTableCell* renderCell = static_cast<RenderTableCell*>(m_renderer); - - // If this cell is in the first column, there is no need to continue. - int col = renderCell->col(); - if (!col) - return 0; - - int row = renderCell->row(); - - RenderTableSection* section = renderCell->section(); - if (!section) - return 0; - - RenderTableCell* headerCell = section->cellAt(row, 0).cell; - if (!headerCell || headerCell == renderCell) - return 0; - - Node* cellElement = headerCell->element(); - if (!cellElement || !cellElement->hasTagName(thTag)) - return 0; - - return axObjectCache()->get(headerCell); -} - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTableCell.h b/src/3rdparty/webkit/WebCore/page/AccessibilityTableCell.h deleted file mode 100644 index 8f8dd77..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTableCell.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2008 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 AccessibilityTableCell_h -#define AccessibilityTableCell_h - -#include "AccessibilityRenderObject.h" - -namespace WebCore { - -class AccessibilityTableCell : public AccessibilityRenderObject { - -private: - AccessibilityTableCell(RenderObject*); -public: - static PassRefPtr<AccessibilityTableCell> create(RenderObject*); - virtual ~AccessibilityTableCell(); - - virtual bool isTableCell() const; - virtual AccessibilityRole roleValue() const; - - virtual bool accessibilityIsIgnored() const; - - // fills in the start location and row span of cell - void rowIndexRange(pair<int, int>& rowRange); - // fills in the start location and column span of cell - void columnIndexRange(pair<int, int>& columnRange); - - // if a table cell is not exposed as a table cell, a TH element can - // serve as its title ui element - AccessibilityObject* titleUIElement() const; - -private: - int m_rowIndex; - -}; - -} // namespace WebCore - -#endif // AccessibilityTableCell_h diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTableColumn.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityTableColumn.cpp deleted file mode 100644 index 6e03af9..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTableColumn.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AccessibilityTableColumn.h" - -#include "AccessibilityTableCell.h" -#include "AXObjectCache.h" -#include "HTMLNames.h" -#include "RenderTable.h" -#include "RenderTableSection.h" -#include "RenderTableCell.h" - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityTableColumn::AccessibilityTableColumn() - : m_parentTable(0) -{ -} - -AccessibilityTableColumn::~AccessibilityTableColumn() -{ -} - -PassRefPtr<AccessibilityTableColumn> AccessibilityTableColumn::create() -{ - return adoptRef(new AccessibilityTableColumn()); -} - -void AccessibilityTableColumn::setParentTable(AccessibilityTable* table) -{ - m_parentTable = table; - - clearChildren(); - addChildren(); -} - -IntRect AccessibilityTableColumn::elementRect() const -{ - // this will be filled in when addChildren is called - return m_columnRect; -} - -IntSize AccessibilityTableColumn::size() const -{ - return elementRect().size(); -} - -const AccessibilityObject::AccessibilityChildrenVector& AccessibilityTableColumn::children() -{ - if (!m_haveChildren) - addChildren(); - return m_children; -} - -AccessibilityObject* AccessibilityTableColumn::headerObject() -{ - if (!m_parentTable) - return 0; - - RenderTable* table = static_cast<RenderTable*>(m_parentTable->renderer()); - - AccessibilityObject* headerObject = 0; - - // try the <thead> section first. this doesn't require th tags - headerObject = headerObjectForSection(table->header(), false); - - if (headerObject) - return headerObject; - - // now try for <th> tags in the first body - headerObject = headerObjectForSection(table->firstBody(), true); - - return headerObject; -} - -AccessibilityObject* AccessibilityTableColumn::headerObjectForSection(RenderTableSection* section, bool thTagRequired) -{ - if (!section) - return 0; - - int numCols = section->numColumns(); - if (m_columnIndex >= numCols) - return 0; - - RenderTableCell* cell = 0; - // also account for cells that have a span - for (int testCol = m_columnIndex; testCol >= 0; --testCol) { - RenderTableCell* testCell = section->cellAt(0, testCol).cell; - if (!testCell) - continue; - - // we've reached a cell that doesn't even overlap our column - // it can't be our header - if ((testCell->col() + (testCell->colSpan()-1)) < m_columnIndex) - break; - - Node* node = testCell->element(); - if (!node) - continue; - - if (thTagRequired && !node->hasTagName(thTag)) - continue; - - cell = testCell; - } - - if (!cell) - return 0; - - return m_parentTable->axObjectCache()->get(cell); -} - -void AccessibilityTableColumn::addChildren() -{ - ASSERT(!m_haveChildren); - - m_haveChildren = true; - if (!m_parentTable) - return; - - int numRows = m_parentTable->rowCount(); - - for (int i = 0; i < numRows; i++) { - AccessibilityTableCell* cell = m_parentTable->cellForColumnAndRow(m_columnIndex, i); - if (!cell) - continue; - - // make sure the last one isn't the same as this one (rowspan cells) - if (m_children.size() > 0 && m_children.last() == cell) - continue; - - m_children.append(cell); - m_columnRect.unite(cell->elementRect()); - } -} - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTableColumn.h b/src/3rdparty/webkit/WebCore/page/AccessibilityTableColumn.h deleted file mode 100644 index 6270398..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTableColumn.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2008 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 AccessibilityTableColumn_h -#define AccessibilityTableColumn_h - -#include "AccessibilityObject.h" -#include "AccessibilityTable.h" -#include "IntRect.h" - -namespace WebCore { - -class RenderTableSection; - -class AccessibilityTableColumn : public AccessibilityObject { - -private: - AccessibilityTableColumn(); -public: - static PassRefPtr<AccessibilityTableColumn> create(); - virtual ~AccessibilityTableColumn(); - - void setParentTable(AccessibilityTable*); - virtual AccessibilityObject* parentObject() const { return m_parentTable; } - AccessibilityObject* headerObject(); - - virtual AccessibilityRole roleValue() const { return ColumnRole; } - virtual bool accessibilityIsIgnored() const { return false; } - virtual bool isTableColumn() const { return true; } - - void setColumnIndex(int columnIndex) { m_columnIndex = columnIndex; } - int columnIndex() const { return m_columnIndex; } - - virtual const AccessibilityChildrenVector& children(); - virtual void addChildren(); - - virtual IntSize size() const; - virtual IntRect elementRect() const; - -private: - AccessibilityTable* m_parentTable; - int m_columnIndex; - IntRect m_columnRect; - - AccessibilityObject* headerObjectForSection(RenderTableSection*, bool thTagRequired); -}; - -} // namespace WebCore - -#endif // AccessibilityTableColumn_h diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTableHeaderContainer.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityTableHeaderContainer.cpp deleted file mode 100644 index af9de39..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTableHeaderContainer.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AccessibilityTableHeaderContainer.h" - -#include "AccessibilityTable.h" -#include "AXObjectCache.h" - -using namespace std; - -namespace WebCore { - -AccessibilityTableHeaderContainer::AccessibilityTableHeaderContainer() - : m_parentTable(0) -{ -} - -AccessibilityTableHeaderContainer::~AccessibilityTableHeaderContainer() -{ -} - -PassRefPtr<AccessibilityTableHeaderContainer> AccessibilityTableHeaderContainer::create() -{ - return adoptRef(new AccessibilityTableHeaderContainer()); -} - -const AccessibilityObject::AccessibilityChildrenVector& AccessibilityTableHeaderContainer::children() -{ - if (!m_haveChildren) - addChildren(); - return m_children; -} - -IntRect AccessibilityTableHeaderContainer::elementRect() const -{ - // this will be filled in when addChildren is called - return m_headerRect; -} - -IntSize AccessibilityTableHeaderContainer::size() const -{ - return elementRect().size(); -} - -void AccessibilityTableHeaderContainer::addChildren() -{ - ASSERT(!m_haveChildren); - - m_haveChildren = true; - if (!m_parentTable || !m_parentTable->isDataTable()) - return; - - static_cast<AccessibilityTable*>(m_parentTable)->columnHeaders(m_children); - - unsigned length = m_children.size(); - for (unsigned k = 0; k < length; ++k) { - m_headerRect.unite(m_children[k]->elementRect()); - } -} - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTableHeaderContainer.h b/src/3rdparty/webkit/WebCore/page/AccessibilityTableHeaderContainer.h deleted file mode 100644 index 8a9448a..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTableHeaderContainer.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2008 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 AccessibilityTableHeaderContainer_h -#define AccessibilityTableHeaderContainer_h - -#include "AccessibilityObject.h" -#include "AccessibilityTable.h" -#include "IntRect.h" - -namespace WebCore { - -class AccessibilityTableHeaderContainer : public AccessibilityObject { - -private: - AccessibilityTableHeaderContainer(); -public: - static PassRefPtr<AccessibilityTableHeaderContainer> create(); - virtual ~AccessibilityTableHeaderContainer(); - - virtual AccessibilityRole roleValue() const { return TableHeaderContainerRole; } - - void setParentTable(AccessibilityTable* table) { m_parentTable = table; } - virtual AccessibilityObject* parentObject() const { return m_parentTable; } - - virtual bool accessibilityIsIgnored() const { return false; } - - virtual const AccessibilityChildrenVector& children(); - virtual void addChildren(); - - virtual IntSize size() const; - virtual IntRect elementRect() const; - -private: - AccessibilityTable* m_parentTable; - IntRect m_headerRect; - -}; - -} // namespace WebCore - -#endif // AccessibilityTableHeaderContainer_h diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTableRow.cpp b/src/3rdparty/webkit/WebCore/page/AccessibilityTableRow.cpp deleted file mode 100644 index caccff5..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTableRow.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "config.h" -#include "AccessibilityTableRow.h" - -#include "AccessibilityTableCell.h" -#include "AXObjectCache.h" -#include "HTMLNames.h" -#include "HTMLTableRowElement.h" -#include "RenderObject.h" -#include "RenderTableCell.h" -#include "RenderTableRow.h" - -using namespace std; - -namespace WebCore { - -using namespace HTMLNames; - -AccessibilityTableRow::AccessibilityTableRow(RenderObject* renderer) - : AccessibilityRenderObject(renderer) -{ -} - -AccessibilityTableRow::~AccessibilityTableRow() -{ -} - -PassRefPtr<AccessibilityTableRow> AccessibilityTableRow::create(RenderObject* renderer) -{ - return adoptRef(new AccessibilityTableRow(renderer)); -} - -AccessibilityRole AccessibilityTableRow::roleValue() const -{ - if (!isTableRow()) - return AccessibilityRenderObject::roleValue(); - - return RowRole; -} - -bool AccessibilityTableRow::isTableRow() const -{ - if (!m_renderer) - return true; - - AccessibilityObject* renderTable = axObjectCache()->get(static_cast<RenderTableRow*>(m_renderer)->table()); - if (!renderTable->isDataTable()) - return false; - - return true; -} - -bool AccessibilityTableRow::accessibilityIsIgnored() const -{ - if (!isTableRow()) - return AccessibilityRenderObject::accessibilityIsIgnored(); - - return false; -} - -AccessibilityObject* AccessibilityTableRow::headerObject() -{ - AccessibilityChildrenVector rowChildren = children(); - if (!rowChildren.size()) - return 0; - - // check the first element in the row to see if it is a TH element - AccessibilityObject* cell = rowChildren[0].get(); - if (!cell->isTableCell()) - return 0; - - RenderObject* cellRenderer = static_cast<AccessibilityTableCell*>(cell)->renderer(); - if (!cellRenderer) - return 0; - - Node* cellNode = cellRenderer->element(); - if (!cellNode || !cellNode->hasTagName(thTag)) - return 0; - - return cell; -} - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/AccessibilityTableRow.h b/src/3rdparty/webkit/WebCore/page/AccessibilityTableRow.h deleted file mode 100644 index 0ec7f04..0000000 --- a/src/3rdparty/webkit/WebCore/page/AccessibilityTableRow.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2008 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 AccessibilityTableRow_h -#define AccessibilityTableRow_h - -#include "AccessibilityRenderObject.h" - -namespace WebCore { - -class AccessibilityTableRow : public AccessibilityRenderObject { - -private: - AccessibilityTableRow(RenderObject*); -public: - static PassRefPtr<AccessibilityTableRow> create(RenderObject*); - virtual ~AccessibilityTableRow(); - - virtual bool isTableRow() const; - virtual AccessibilityRole roleValue() const; - - // retrieves the "row" header (a th tag in the rightmost column) - AccessibilityObject* headerObject(); - - virtual bool accessibilityIsIgnored() const; - - void setRowIndex(int rowIndex) { m_rowIndex = rowIndex; } - int rowIndex() const { return m_rowIndex; } - - // allows the table to add other children that may not originate - // in the row, but their col/row spans overlap into it - void appendChild(AccessibilityObject*); - -private: - int m_rowIndex; -}; - -} // namespace WebCore - -#endif // AccessibilityTableRow_h diff --git a/src/3rdparty/webkit/WebCore/page/BarInfo.cpp b/src/3rdparty/webkit/WebCore/page/BarInfo.cpp index 153aee0..f6a1210 100644 --- a/src/3rdparty/webkit/WebCore/page/BarInfo.cpp +++ b/src/3rdparty/webkit/WebCore/page/BarInfo.cpp @@ -41,11 +41,21 @@ BarInfo::BarInfo(Frame* frame, Type type) { } +Frame* BarInfo::frame() const +{ + return m_frame; +} + void BarInfo::disconnectFrame() { m_frame = 0; } +BarInfo::Type BarInfo::type() const +{ + return m_type; +} + bool BarInfo::visible() const { if (!m_frame) diff --git a/src/3rdparty/webkit/WebCore/page/BarInfo.h b/src/3rdparty/webkit/WebCore/page/BarInfo.h index 4cbbcfc..376b8fc 100644 --- a/src/3rdparty/webkit/WebCore/page/BarInfo.h +++ b/src/3rdparty/webkit/WebCore/page/BarInfo.h @@ -42,8 +42,11 @@ namespace WebCore { static PassRefPtr<BarInfo> create(Frame* frame, Type type) { return adoptRef(new BarInfo(frame, type)); } + Frame* frame() const; void disconnectFrame(); + Type type() const; + bool visible() const; private: diff --git a/src/3rdparty/webkit/WebCore/page/Chrome.cpp b/src/3rdparty/webkit/WebCore/page/Chrome.cpp index 1f6e198..86de82e 100644 --- a/src/3rdparty/webkit/WebCore/page/Chrome.cpp +++ b/src/3rdparty/webkit/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,13 +28,14 @@ #include "FloatRect.h" #include "Frame.h" #include "FrameTree.h" +#include "Geolocation.h" #include "HTMLFormElement.h" #include "HTMLInputElement.h" #include "HTMLNames.h" #include "HitTestResult.h" #include "InspectorController.h" #include "Page.h" -#include "PageGroup.h" +#include "PageGroupLoadDeferrer.h" #include "ResourceHandle.h" #include "ScriptController.h" #include "SecurityOrigin.h" @@ -53,14 +54,6 @@ namespace WebCore { using namespace HTMLNames; using namespace std; -class PageGroupLoadDeferrer : Noncopyable { -public: - PageGroupLoadDeferrer(Page*, bool deferSelf); - ~PageGroupLoadDeferrer(); -private: - Vector<RefPtr<Frame>, 16> m_deferredFrames; -}; - Chrome::Chrome(Page* page, ChromeClient* client) : m_page(page) , m_client(client) @@ -151,13 +144,14 @@ void Chrome::takeFocus(FocusDirection direction) const Page* Chrome::createWindow(Frame* frame, const FrameLoadRequest& request, const WindowFeatures& features) const { Page* newPage = m_client->createWindow(frame, request, features); + #if ENABLE(DOM_STORAGE) - if (newPage) { if (SessionStorage* oldSessionStorage = m_page->sessionStorage(false)) - newPage->setSessionStorage(oldSessionStorage->copy(newPage)); + newPage->setSessionStorage(oldSessionStorage->copy(newPage)); } #endif + return newPage; } @@ -259,10 +253,7 @@ void Chrome::runJavaScriptAlert(Frame* frame, const String& message) PageGroupLoadDeferrer deferrer(m_page, true); ASSERT(frame); - String text = message; - text.replace('\\', frame->backslashAsCurrencySymbol()); - - m_client->runJavaScriptAlert(frame, text); + m_client->runJavaScriptAlert(frame, frame->displayStringModifiedByEncoding(message)); } bool Chrome::runJavaScriptConfirm(Frame* frame, const String& message) @@ -272,10 +263,7 @@ bool Chrome::runJavaScriptConfirm(Frame* frame, const String& message) PageGroupLoadDeferrer deferrer(m_page, true); ASSERT(frame); - String text = message; - text.replace('\\', frame->backslashAsCurrencySymbol()); - - return m_client->runJavaScriptConfirm(frame, text); + return m_client->runJavaScriptConfirm(frame, frame->displayStringModifiedByEncoding(message)); } bool Chrome::runJavaScriptPrompt(Frame* frame, const String& prompt, const String& defaultValue, String& result) @@ -285,15 +273,10 @@ bool Chrome::runJavaScriptPrompt(Frame* frame, const String& prompt, const Strin PageGroupLoadDeferrer deferrer(m_page, true); ASSERT(frame); - String promptText = prompt; - promptText.replace('\\', frame->backslashAsCurrencySymbol()); - String defaultValueText = defaultValue; - defaultValueText.replace('\\', frame->backslashAsCurrencySymbol()); - - bool ok = m_client->runJavaScriptPrompt(frame, promptText, defaultValueText, result); + bool ok = m_client->runJavaScriptPrompt(frame, frame->displayStringModifiedByEncoding(prompt), frame->displayStringModifiedByEncoding(defaultValue), result); if (ok) - result.replace(frame->backslashAsCurrencySymbol(), '\\'); + result = frame->displayStringModifiedByEncoding(result); return ok; } @@ -301,10 +284,7 @@ bool Chrome::runJavaScriptPrompt(Frame* frame, const String& prompt, const Strin void Chrome::setStatusbarText(Frame* frame, const String& status) { ASSERT(frame); - String text = status; - text.replace('\\', frame->backslashAsCurrencySymbol()); - - m_client->setStatusbarText(text); + m_client->setStatusbarText(frame->displayStringModifiedByEncoding(status)); } bool Chrome::shouldInterruptJavaScript() @@ -391,20 +371,26 @@ void Chrome::print(Frame* frame) m_client->print(frame); } -void Chrome::disableSuddenTermination() +void Chrome::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation) { - m_client->disableSuddenTermination(); -} + // 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); -void Chrome::enableSuddenTermination() -{ - m_client->enableSuddenTermination(); + ASSERT(frame); + m_client->requestGeolocationPermissionForFrame(frame, geolocation); } void Chrome::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> fileChooser) { m_client->runOpenPanel(frame, fileChooser); } + +bool Chrome::setCursor(PlatformCursorHandle cursor) +{ + return m_client->setCursor(cursor); +} + // -------- #if ENABLE(DASHBOARD_SUPPORT) @@ -437,14 +423,6 @@ String ChromeClient::generateReplacementFile(const String&) return String(); } -void ChromeClient::disableSuddenTermination() -{ -} - -void ChromeClient::enableSuddenTermination() -{ -} - bool ChromeClient::paintCustomScrollbar(GraphicsContext*, const FloatRect&, ScrollbarControlSize, ScrollbarControlState, ScrollbarPart, bool, float, float, ScrollbarControlPartMask) @@ -457,49 +435,5 @@ bool ChromeClient::paintCustomScrollCorner(GraphicsContext*, const FloatRect&) return false; } -// -------- - -PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf) -{ - const HashSet<Page*>& pages = page->group().pages(); - - HashSet<Page*>::const_iterator end = pages.end(); - for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) { - Page* otherPage = *it; - if ((deferSelf || otherPage != page)) { - if (!otherPage->defersLoading()) - 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(); - } -#endif - } - } - - size_t count = m_deferredFrames.size(); - for (size_t i = 0; i < count; ++i) - if (Page* page = m_deferredFrames[i]->page()) - page->setDefersLoading(true); -} - -PageGroupLoadDeferrer::~PageGroupLoadDeferrer() -{ - for (size_t i = 0; i < m_deferredFrames.size(); ++i) { - if (Page* page = m_deferredFrames[i]->page()) { - page->setDefersLoading(false); - -#if !PLATFORM(MAC) - for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { - if (Document* document = frame->document()) - document->resumeActiveDOMObjects(); - } -#endif - } - } -} - } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Chrome.h b/src/3rdparty/webkit/WebCore/page/Chrome.h index 47b912d..c26e450 100644 --- a/src/3rdparty/webkit/WebCore/page/Chrome.h +++ b/src/3rdparty/webkit/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 @@ -20,6 +20,7 @@ #ifndef Chrome_h #define Chrome_h +#include "Cursor.h" #include "FileChooser.h" #include "FocusDirection.h" #include "HostWindow.h" @@ -38,6 +39,7 @@ namespace WebCore { class ContextMenu; class FloatRect; class Frame; + class Geolocation; class HitTestResult; class IntRect; class Page; @@ -116,11 +118,12 @@ namespace WebCore { void print(Frame*); - void enableSuddenTermination(); - void disableSuddenTermination(); + void requestGeolocationPermissionForFrame(Frame*, Geolocation*); void runOpenPanel(Frame*, PassRefPtr<FileChooser>); + bool setCursor(PlatformCursorHandle); + #if PLATFORM(MAC) void focusNSView(NSView*); #endif diff --git a/src/3rdparty/webkit/WebCore/page/ChromeClient.h b/src/3rdparty/webkit/WebCore/page/ChromeClient.h index 5d90b2f..e155754 100644 --- a/src/3rdparty/webkit/WebCore/page/ChromeClient.h +++ b/src/3rdparty/webkit/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 @@ -20,11 +20,15 @@ #ifndef ChromeClient_h #define ChromeClient_h -#include "GraphicsContext.h" +#include "Console.h" +#include "Cursor.h" #include "FocusDirection.h" -#include "ScrollTypes.h" +#include "GraphicsContext.h" +#include "HTMLParserQuirks.h" #include "HostWindow.h" +#include "ScrollTypes.h" #include <wtf/Forward.h> +#include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> #if PLATFORM(MAC) @@ -42,16 +46,22 @@ namespace WebCore { class FileChooser; class FloatRect; class Frame; + class Geolocation; + class HTMLParserQuirks; 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; @@ -93,7 +103,7 @@ namespace WebCore { virtual void setResizable(bool) = 0; - virtual void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID) = 0; + virtual void addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned int lineNumber, const String& sourceID) = 0; virtual bool canRunBeforeUnloadConfirmPanel() = 0; virtual bool runBeforeUnloadConfirmPanel(const String& message, Frame* frame) = 0; @@ -116,7 +126,7 @@ namespace WebCore { virtual IntRect windowToScreen(const IntRect&) const = 0; virtual PlatformWidget platformWindow() const = 0; virtual void contentsSizeChanged(Frame*, const IntSize&) const = 0; - virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const {} // Platforms other than Mac can implement this if it ever becomes necessary for them to do so. + virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const = 0; // Currently only Mac has a non empty implementation. // End methods used by HostWindow. virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags) = 0; @@ -125,7 +135,9 @@ namespace WebCore { virtual void print(Frame*) = 0; +#if ENABLE(DATABASE) virtual void exceededDatabaseQuota(Frame*, const String& databaseName) = 0; +#endif #if ENABLE(DASHBOARD_SUPPORT) virtual void dashboardRegionsChanged(); @@ -139,21 +151,37 @@ namespace WebCore { virtual bool shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename); virtual String generateReplacementFile(const String& path); - - virtual void enableSuddenTermination(); - virtual void disableSuddenTermination(); virtual bool paintCustomScrollbar(GraphicsContext*, const FloatRect&, ScrollbarControlSize, ScrollbarControlState, ScrollbarPart pressedPart, bool vertical, 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*) = 0; + virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>) = 0; + virtual bool setCursor(PlatformCursorHandle) = 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; + virtual PassOwnPtr<HTMLParserQuirks> createHTMLParserQuirks() = 0; + +#if USE(ACCELERATED_COMPOSITING) + // Pass 0 as the GraphicsLayer to detatch the root layer. + virtual void attachRootGraphicsLayer(Frame*, GraphicsLayer*) = 0; + // 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() = 0; + // Sets a flag to specify that the view needs to be updated, so we need + // to do an eager layout before the drawing. + virtual void scheduleViewUpdate() = 0; +#endif + #if PLATFORM(MAC) virtual KeyboardUIMode keyboardUIMode() { return KeyboardAccessDefault; } diff --git a/src/3rdparty/webkit/WebCore/page/Console.cpp b/src/3rdparty/webkit/WebCore/page/Console.cpp index 8755f0e..99a0fc8 100644 --- a/src/3rdparty/webkit/WebCore/page/Console.cpp +++ b/src/3rdparty/webkit/WebCore/page/Console.cpp @@ -39,7 +39,7 @@ #include "PageGroup.h" #include "PlatformString.h" -#if USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) #include <profiler/Profiler.h> #endif @@ -53,6 +53,11 @@ Console::Console(Frame* frame) { } +Frame* Console::frame() const +{ + return m_frame; +} + void Console::disconnectFrame() { m_frame = 0; @@ -68,7 +73,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 +82,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 +105,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 +119,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 +128,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); @@ -136,7 +156,7 @@ void Console::addMessage(MessageSource source, MessageLevel level, const String& return; if (source == JSMessageSource || source == WMLMessageSource) - page->chrome()->client()->addMessageToConsole(message, lineNumber, sourceURL); + page->chrome()->client()->addMessageToConsole(source, level, message, lineNumber, sourceURL); page->inspectorController()->addMessageToConsole(source, level, message, lineNumber, sourceURL); @@ -160,8 +180,8 @@ void Console::addMessage(MessageLevel level, ScriptCallStack* callStack, bool ac return; String message; - if (getFirstArgumentAsString(lastCaller, message)) - page->chrome()->client()->addMessageToConsole(message, lastCaller.lineNumber(), lastCaller.sourceURL().prettyURL()); + if (getFirstArgumentAsString(callStack->state(), lastCaller, message)) + page->chrome()->client()->addMessageToConsole(JSMessageSource, level, message, lastCaller.lineNumber(), lastCaller.sourceURL().prettyURL()); page->inspectorController()->addMessageToConsole(JSMessageSource, level, callStack); @@ -207,7 +227,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,12 +264,12 @@ 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()); } -#if USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) void Console::profile(const JSC::UString& title, ScriptCallStack* callStack) { @@ -256,13 +277,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/src/3rdparty/webkit/WebCore/page/Console.h b/src/3rdparty/webkit/WebCore/page/Console.h index 7301fc9..79396ea 100644 --- a/src/3rdparty/webkit/WebCore/page/Console.h +++ b/src/3rdparty/webkit/WebCore/page/Console.h @@ -31,7 +31,7 @@ #include "PlatformString.h" -#if USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) #include <profiler/Profile.h> #endif @@ -40,7 +40,7 @@ namespace WebCore { -#if USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) typedef Vector<RefPtr<JSC::Profile> > ProfilesArray; #endif @@ -64,8 +64,8 @@ namespace WebCore { LogMessageLevel, WarningMessageLevel, ErrorMessageLevel, + // FIXME: the remaining levels should become a new MessageType enum. ObjectMessageLevel, - NodeMessageLevel, TraceMessageLevel, StartGroupMessageLevel, EndGroupMessageLevel @@ -75,6 +75,7 @@ namespace WebCore { public: static PassRefPtr<Console> create(Frame* frame) { return adoptRef(new Console(frame)); } + Frame* frame() const; void disconnectFrame(); void addMessage(MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceURL); @@ -89,7 +90,7 @@ namespace WebCore { void trace(ScriptCallStack*); void assertCondition(bool condition, ScriptCallStack*); void count(ScriptCallStack*); -#if USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) void profile(const JSC::UString&, ScriptCallStack*); void profileEnd(const JSC::UString&, ScriptCallStack*); #endif @@ -101,7 +102,7 @@ namespace WebCore { static bool shouldPrintExceptions(); static void setShouldPrintExceptions(bool); -#if USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) const ProfilesArray& profiles() const { return m_profiles; } #endif @@ -112,7 +113,7 @@ namespace WebCore { Console(Frame*); Frame* m_frame; -#if USE(JSC) +#if ENABLE(JAVASCRIPT_DEBUGGER) ProfilesArray m_profiles; #endif }; diff --git a/src/3rdparty/webkit/WebCore/page/Console.idl b/src/3rdparty/webkit/WebCore/page/Console.idl index fb7688d..4803508 100644 --- a/src/3rdparty/webkit/WebCore/page/Console.idl +++ b/src/3rdparty/webkit/WebCore/page/Console.idl @@ -30,7 +30,7 @@ module window { interface Console { -#if !defined(V8_BINDING) +#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER readonly attribute [CustomGetter] Array profiles; #endif @@ -45,7 +45,7 @@ module window { [CustomArgumentHandling, ImplementationFunction=assertCondition] void assert(in boolean condition); [CustomArgumentHandling] void count(); -#if !defined(V8_BINDING) +#if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER [CustomArgumentHandling] void profile(in [ConvertUndefinedOrNullToNullString] DOMString title); [CustomArgumentHandling] void profileEnd(in [ConvertUndefinedOrNullToNullString] DOMString title); #endif diff --git a/src/3rdparty/webkit/WebCore/page/ContextMenuController.cpp b/src/3rdparty/webkit/WebCore/page/ContextMenuController.cpp index 5e9f8b5..58e6519 100644 --- a/src/3rdparty/webkit/WebCore/page/ContextMenuController.cpp +++ b/src/3rdparty/webkit/WebCore/page/ContextMenuController.cpp @@ -37,11 +37,13 @@ #include "Event.h" #include "EventHandler.h" #include "EventNames.h" +#include "FormState.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoadRequest.h" #include "HitTestRequest.h" #include "HitTestResult.h" +#include "HTMLFormElement.h" #include "InspectorController.h" #include "MouseEvent.h" #include "Node.h" @@ -83,15 +85,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 +190,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: @@ -217,10 +214,10 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item) m_client->lookUpInDictionary(frame); break; case ContextMenuItemTagOpenLink: - if (Frame* targetFrame = result.targetFrame()) - targetFrame->loader()->loadFrameRequestWithFormAndValues(FrameLoadRequest(ResourceRequest(result.absoluteLinkURL(), - frame->loader()->outgoingReferrer())), false, 0, 0, HashMap<String, String>()); - else + if (Frame* targetFrame = result.targetFrame()) { + targetFrame->loader()->loadFrameRequest(FrameLoadRequest(ResourceRequest(result.absoluteLinkURL(), + frame->loader()->outgoingReferrer())), false, false, 0, 0); + } else openNewWindow(result.absoluteLinkURL(), frame); break; case ContextMenuItemTagBold: @@ -238,7 +235,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(); @@ -298,6 +295,41 @@ void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item) frame->editor()->showColorPanel(); break; #endif +#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + case ContextMenuItemTagMakeUpperCase: + frame->editor()->uppercaseWord(); + break; + case ContextMenuItemTagMakeLowerCase: + frame->editor()->lowercaseWord(); + break; + case ContextMenuItemTagCapitalize: + frame->editor()->capitalizeWord(); + break; + case ContextMenuItemTagShowSubstitutions: + frame->editor()->showSubstitutionsPanel(); + break; + case ContextMenuItemTagSmartCopyPaste: + frame->editor()->toggleSmartInsertDelete(); + break; + case ContextMenuItemTagSmartQuotes: + frame->editor()->toggleAutomaticQuoteSubstitution(); + break; + case ContextMenuItemTagSmartDashes: + frame->editor()->toggleAutomaticDashSubstitution(); + break; + case ContextMenuItemTagSmartLinks: + frame->editor()->toggleAutomaticLinkDetection(); + break; + case ContextMenuItemTagTextReplacement: + frame->editor()->toggleAutomaticTextReplacement(); + break; + case ContextMenuItemTagCorrectSpellingAutomatically: + frame->editor()->toggleAutomaticSpellingCorrection(); + break; + case ContextMenuItemTagChangeBack: + frame->editor()->changeBackToReplacedString(result.replacedString()); + break; +#endif case ContextMenuItemTagInspectElement: if (Page* page = frame->page()) page->inspectorController()->inspect(result.innerNonSharedNode()); diff --git a/src/3rdparty/webkit/WebCore/page/win/AccessibilityObjectWin.cpp b/src/3rdparty/webkit/WebCore/page/Coordinates.cpp index 0a386c7..637a8c2 100644 --- a/src/3rdparty/webkit/WebCore/page/win/AccessibilityObjectWin.cpp +++ b/src/3rdparty/webkit/WebCore/page/Coordinates.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * 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 @@ -24,17 +24,15 @@ */ #include "config.h" -#include "AccessibilityObject.h" - -#if HAVE(ACCESSIBILITY) +#include "Coordinates.h" namespace WebCore { -bool AccessibilityObject::accessibilityIgnoreAttachment() const +String Coordinates::toString() const { - return false; + 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 - -#endif // HAVE(ACCESSIBILITY) diff --git a/src/3rdparty/webkit/WebCore/page/Coordinates.h b/src/3rdparty/webkit/WebCore/page/Coordinates.h new file mode 100644 index 0000000..acb5dd0 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/Coordinates.h @@ -0,0 +1,88 @@ +/* + * 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, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) { return adoptRef(new Coordinates(latitude, longitude, providesAltitude, altitude, accuracy, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, 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; } + + bool canProvideAltitude() const { return m_canProvideAltitude; } + bool canProvideAltitudeAccuracy() const { return m_canProvideAltitudeAccuracy; } + bool canProvideHeading() const { return m_canProvideHeading; } + bool canProvideSpeed() const { return m_canProvideSpeed; } + + String toString() const; + +private: + Coordinates(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed) + : m_latitude(latitude) + , m_longitude(longitude) + , m_altitude(altitude) + , m_accuracy(accuracy) + , m_altitudeAccuracy(altitudeAccuracy) + , m_heading(heading) + , m_speed(speed) + , m_canProvideAltitude(providesAltitude) + , m_canProvideAltitudeAccuracy(providesAltitudeAccuracy) + , m_canProvideHeading(providesHeading) + , m_canProvideSpeed(providesSpeed) + { + } + + double m_latitude; + double m_longitude; + double m_altitude; + double m_accuracy; + double m_altitudeAccuracy; + double m_heading; + double m_speed; + + bool m_canProvideAltitude; + bool m_canProvideAltitudeAccuracy; + bool m_canProvideHeading; + bool m_canProvideSpeed; +}; + +} // namespace WebCore + +#endif // Coordinates_h diff --git a/src/3rdparty/webkit/WebCore/page/chromium/AccessibilityObjectWrapper.h b/src/3rdparty/webkit/WebCore/page/Coordinates.idl index 0846d20..f6c82b5 100644 --- a/src/3rdparty/webkit/WebCore/page/chromium/AccessibilityObjectWrapper.h +++ b/src/3rdparty/webkit/WebCore/page/Coordinates.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * 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 @@ -20,31 +20,22 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef AccessibilityObjectWrapper_h -#define AccessibilityObjectWrapper_h +module core { -namespace WebCore { + interface Coordinates { + readonly attribute double latitude; + readonly attribute double longitude; + readonly attribute [Custom] double altitude; + readonly attribute double accuracy; + readonly attribute [Custom] double altitudeAccuracy; + readonly attribute [Custom] double heading; + readonly attribute [Custom] double speed; - class AccessibilityObject; - - class AccessibilityObjectWrapper : public RefCounted<AccessibilityObjectWrapper> { - public: - virtual ~AccessibilityObjectWrapper() {} - virtual void detach() = 0; - bool attached() const { return m_object; } - AccessibilityObject* accessibilityObject() const { return m_object; } - - protected: - AccessibilityObjectWrapper(AccessibilityObject* obj) - : RefCounted<AccessibilityObjectWrapper>(0), m_object(obj) { } - AccessibilityObjectWrapper() : m_object(0) { } - - AccessibilityObject* m_object; +#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT + [DontEnum] DOMString toString(); +#endif }; - -} // namespace WebCore - -#endif // AccessibilityObjectWrapper_h +} diff --git a/src/3rdparty/webkit/WebCore/page/DOMSelection.cpp b/src/3rdparty/webkit/WebCore/page/DOMSelection.cpp index 5dab325..3b54f02 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMSelection.cpp +++ b/src/3rdparty/webkit/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()).deprecatedEditingOffset(); } -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()).deprecatedEditingOffset(); } -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()).deprecatedEditingOffset(); +} - 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()).deprecatedEditingOffset(); } 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/src/3rdparty/webkit/WebCore/page/DOMSelection.h b/src/3rdparty/webkit/WebCore/page/DOMSelection.h index fd8d1fc..6a914d6 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMSelection.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/page/DOMSelection.idl b/src/3rdparty/webkit/WebCore/page/DOMSelection.idl index 85d23bf..be6c2b4 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMSelection.idl +++ b/src/3rdparty/webkit/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,43 +29,58 @@ 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(); void addRange(in Range range); -#if defined(LANGUAGE_JAVASCRIPT) +#if defined(LANGUAGE_JAVASCRIPT) && 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/src/3rdparty/webkit/WebCore/page/DOMTimer.cpp b/src/3rdparty/webkit/WebCore/page/DOMTimer.cpp new file mode 100644 index 0000000..1cc7730 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/DOMTimer.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2008 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. + * + */ + +#include "config.h" +#include "DOMTimer.h" + +#include "ScheduledAction.h" +#include "ScriptExecutionContext.h" +#include <wtf/HashSet.h> +#include <wtf/StdLibExtras.h> + +using namespace std; + +namespace WebCore { + +static const int maxTimerNestingLevel = 5; +static const double oneMillisecond = 0.001; +double DOMTimer::s_minTimerInterval = 0.010; // 10 milliseconds + +static int timerNestingLevel = 0; + +DOMTimer::DOMTimer(ScriptExecutionContext* context, ScheduledAction* action, int timeout, bool singleShot) + : ActiveDOMObject(context, this) + , m_action(action) + , m_nextFireInterval(0) + , m_repeatInterval(0) +{ + static int lastUsedTimeoutId = 0; + ++lastUsedTimeoutId; + // Avoid wraparound going negative on us. + if (lastUsedTimeoutId <= 0) + lastUsedTimeoutId = 1; + m_timeoutId = lastUsedTimeoutId; + + m_nestingLevel = timerNestingLevel + 1; + + 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 < s_minTimerInterval && m_nestingLevel >= maxTimerNestingLevel) + intervalMilliseconds = s_minTimerInterval; + if (singleShot) + startOneShot(intervalMilliseconds); + else + startRepeating(intervalMilliseconds); +} + +DOMTimer::~DOMTimer() +{ + if (scriptExecutionContext()) { + scriptExecutionContext()->removeTimeout(m_timeoutId); + } +} + +int DOMTimer::install(ScriptExecutionContext* context, ScheduledAction* action, int timeout, bool singleShot) +{ + // DOMTimer constructor links the new timer into a list of ActiveDOMObjects held by the 'context'. + // The timer is deleted when context is deleted (DOMTimer::contextDestroyed) or explicitly via DOMTimer::removeById(), + // or if it is a one-time timer and it has fired (DOMTimer::fired). + DOMTimer* timer = new DOMTimer(context, action, timeout, singleShot); + return timer->m_timeoutId; +} + +void DOMTimer::removeById(ScriptExecutionContext* context, int timeoutId) +{ + // timeout IDs have to be positive, and 0 and -1 are unsafe to + // even look up since they are the empty and deleted value + // respectively + if (timeoutId <= 0) + return; + delete context->findTimeout(timeoutId); +} + +void DOMTimer::fired() +{ + ScriptExecutionContext* context = scriptExecutionContext(); + timerNestingLevel = m_nestingLevel; + + // Simple case for non-one-shot timers. + if (isActive()) { + if (repeatInterval() && repeatInterval() < s_minTimerInterval) { + m_nestingLevel++; + if (m_nestingLevel >= maxTimerNestingLevel) + augmentRepeatInterval(s_minTimerInterval - repeatInterval()); + } + + // No access to member variables after this point, it can delete the timer. + m_action->execute(context); + return; + } + + // Delete timer before executing the action for one-shot timers. + ScheduledAction* action = m_action.release(); + + // No access to member variables after this point. + delete this; + + action->execute(context); + delete action; + timerNestingLevel = 0; +} + +bool DOMTimer::hasPendingActivity() const +{ + return isActive(); +} + +void DOMTimer::contextDestroyed() +{ + ActiveDOMObject::contextDestroyed(); + delete this; +} + +void DOMTimer::stop() +{ + TimerBase::stop(); + // Need to release JS objects potentially protected by ScheduledAction + // because they can form circular references back to the ScriptExecutionContext + // which will cause a memory leak. + m_action.clear(); +} + +void DOMTimer::suspend() +{ + ASSERT(m_nextFireInterval == 0 && m_repeatInterval == 0); + m_nextFireInterval = nextFireInterval(); + m_repeatInterval = repeatInterval(); + TimerBase::stop(); +} + +void DOMTimer::resume() +{ + start(m_nextFireInterval, m_repeatInterval); + m_nextFireInterval = 0; + m_repeatInterval = 0; +} + + +bool DOMTimer::canSuspend() const +{ + return true; +} + +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/DOMTimer.h b/src/3rdparty/webkit/WebCore/page/DOMTimer.h new file mode 100644 index 0000000..f6343fc --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/DOMTimer.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2008 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 DOMTimer_h +#define DOMTimer_h + +#include "ActiveDOMObject.h" +#include "Timer.h" +#include <wtf/OwnPtr.h> + +namespace WebCore { + +class ScheduledAction; + +class DOMTimer : public TimerBase, public ActiveDOMObject { +public: + virtual ~DOMTimer(); + // Creates a new timer owned by specified ScriptExecutionContext, starts it + // and returns its Id. + static int install(ScriptExecutionContext*, ScheduledAction*, int timeout, bool singleShot); + static void removeById(ScriptExecutionContext*, int timeoutId); + + // ActiveDOMObject + virtual bool hasPendingActivity() const; + virtual void contextDestroyed(); + virtual void stop(); + virtual bool canSuspend() const; + 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(); + + int m_timeoutId; + int m_nestingLevel; + OwnPtr<ScheduledAction> m_action; + double m_nextFireInterval; + double m_repeatInterval; + static double s_minTimerInterval; +}; + +} // namespace WebCore + +#endif // DOMTimer_h + diff --git a/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp b/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp index dd14fb9..bc1192d 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp +++ b/src/3rdparty/webkit/WebCore/page/DOMWindow.cpp @@ -27,6 +27,7 @@ #include "DOMWindow.h" #include "BarInfo.h" +#include "BeforeUnloadEvent.h" #include "CSSComputedStyleDeclaration.h" #include "CSSRuleList.h" #include "CSSStyleSelector.h" @@ -34,8 +35,10 @@ #include "Chrome.h" #include "Console.h" #include "DOMSelection.h" +#include "DOMTimer.h" #include "Document.h" #include "Element.h" +#include "EventException.h" #include "EventListener.h" #include "EventNames.h" #include "ExceptionCode.h" @@ -46,6 +49,7 @@ #include "FrameView.h" #include "HTMLFrameOwnerElement.h" #include "History.h" +#include "InspectorController.h" #include "Location.h" #include "MessageEvent.h" #include "Navigator.h" @@ -56,6 +60,8 @@ #include "Screen.h" #include "SecurityOrigin.h" #include "Settings.h" +#include "SuddenTermination.h" +#include "WebKitPoint.h" #include <algorithm> #include <wtf/MathExtras.h> @@ -102,6 +108,152 @@ private: RefPtr<SecurityOrigin> m_targetOrigin; }; +typedef HashMap<DOMWindow*, RegisteredEventListenerVector*> DOMWindowRegisteredEventListenerMap; + +static DOMWindowRegisteredEventListenerMap& pendingUnloadEventListenerMap() +{ + DEFINE_STATIC_LOCAL(DOMWindowRegisteredEventListenerMap, eventListenerMap, ()); + return eventListenerMap; +} + +static DOMWindowRegisteredEventListenerMap& pendingBeforeUnloadEventListenerMap() +{ + DEFINE_STATIC_LOCAL(DOMWindowRegisteredEventListenerMap, eventListenerMap, ()); + return eventListenerMap; +} + +static bool allowsPendingBeforeUnloadListeners(DOMWindow* window) +{ + ASSERT_ARG(window, window); + Frame* frame = window->frame(); + Page* page = frame->page(); + return page && frame == page->mainFrame(); +} + +static void addPendingEventListener(DOMWindowRegisteredEventListenerMap& map, DOMWindow* window, RegisteredEventListener* listener) +{ + ASSERT_ARG(window, window); + ASSERT_ARG(listener, listener); + + if (map.isEmpty()) + disableSuddenTermination(); + + pair<DOMWindowRegisteredEventListenerMap::iterator, bool> result = map.add(window, 0); + if (result.second) + result.first->second = new RegisteredEventListenerVector; + result.first->second->append(listener); +} + +static void removePendingEventListener(DOMWindowRegisteredEventListenerMap& map, DOMWindow* window, RegisteredEventListener* listener) +{ + ASSERT_ARG(window, window); + ASSERT_ARG(listener, listener); + + DOMWindowRegisteredEventListenerMap::iterator it = map.find(window); + ASSERT(it != map.end()); + + RegisteredEventListenerVector* listeners = it->second; + size_t index = listeners->find(listener); + ASSERT(index != WTF::notFound); + listeners->remove(index); + + if (!listeners->isEmpty()) + return; + + map.remove(it); + delete listeners; + + if (map.isEmpty()) + enableSuddenTermination(); +} + +static void removePendingEventListeners(DOMWindowRegisteredEventListenerMap& map, DOMWindow* window) +{ + ASSERT_ARG(window, window); + + RegisteredEventListenerVector* listeners = map.take(window); + if (!listeners) + return; + + delete listeners; + + if (map.isEmpty()) + enableSuddenTermination(); +} + +bool DOMWindow::dispatchAllPendingBeforeUnloadEvents() +{ + DOMWindowRegisteredEventListenerMap& map = pendingBeforeUnloadEventListenerMap(); + if (map.isEmpty()) + return true; + + static bool alreadyDispatched = false; + ASSERT(!alreadyDispatched); + if (alreadyDispatched) + return true; + + Vector<RefPtr<DOMWindow> > windows; + DOMWindowRegisteredEventListenerMap::iterator mapEnd = map.end(); + for (DOMWindowRegisteredEventListenerMap::iterator it = map.begin(); it != mapEnd; ++it) + windows.append(it->first); + + size_t size = windows.size(); + for (size_t i = 0; i < size; ++i) { + DOMWindow* window = windows[i].get(); + RegisteredEventListenerVector* listeners = map.get(window); + if (!listeners) + continue; + + RegisteredEventListenerVector listenersCopy = *listeners; + Frame* frame = window->frame(); + if (!frame->shouldClose(&listenersCopy)) + return false; + } + + enableSuddenTermination(); + + alreadyDispatched = true; + + return true; +} + +unsigned DOMWindow::pendingUnloadEventListeners() const +{ + RegisteredEventListenerVector* listeners = pendingUnloadEventListenerMap().get(const_cast<DOMWindow*>(this)); + return listeners ? listeners->size() : 0; +} + +void DOMWindow::dispatchAllPendingUnloadEvents() +{ + DOMWindowRegisteredEventListenerMap& map = pendingUnloadEventListenerMap(); + if (map.isEmpty()) + return; + + static bool alreadyDispatched = false; + ASSERT(!alreadyDispatched); + if (alreadyDispatched) + return; + + Vector<RefPtr<DOMWindow> > windows; + DOMWindowRegisteredEventListenerMap::iterator mapEnd = map.end(); + for (DOMWindowRegisteredEventListenerMap::iterator it = map.begin(); it != mapEnd; ++it) + windows.append(it->first); + + size_t size = windows.size(); + for (size_t i = 0; i < size; ++i) { + DOMWindow* window = windows[i].get(); + RegisteredEventListenerVector* listeners = map.get(window); + if (!listeners) + continue; + RegisteredEventListenerVector listenersCopy = *listeners; + window->dispatchUnloadEvent(&listenersCopy); + } + + enableSuddenTermination(); + + alreadyDispatched = true; +} + // This function: // 1) Validates the pending changes are not changing to NaN // 2) Constrains the window rect to no smaller than 100 in each dimension and no @@ -142,6 +294,62 @@ void DOMWindow::adjustWindowRect(const FloatRect& screen, FloatRect& window, con window.setY(max(screen.y(), min(window.y(), screen.bottom() - window.height()))); } +void DOMWindow::parseModalDialogFeatures(const String& featuresArg, HashMap<String, String>& map) +{ + Vector<String> features; + featuresArg.split(';', features); + Vector<String>::const_iterator end = features.end(); + for (Vector<String>::const_iterator it = features.begin(); it != end; ++it) { + String s = *it; + int pos = s.find('='); + int colonPos = s.find(':'); + if (pos >= 0 && colonPos >= 0) + continue; // ignore any strings that have both = and : + if (pos < 0) + pos = colonPos; + if (pos < 0) { + // null string for value means key without value + map.set(s.stripWhiteSpace().lower(), String()); + } else { + String key = s.left(pos).stripWhiteSpace().lower(); + String val = s.substring(pos + 1).stripWhiteSpace().lower(); + int spacePos = val.find(' '); + if (spacePos != -1) + val = val.left(spacePos); + map.set(key, val); + } + } +} + +bool DOMWindow::allowPopUp(Frame* activeFrame) +{ + ASSERT(activeFrame); + if (activeFrame->script()->processingUserGesture()) + return true; + Settings* settings = activeFrame->settings(); + return settings && settings->javaScriptCanOpenWindowsAutomatically(); +} + +bool DOMWindow::canShowModalDialog(const Frame* frame) +{ + if (!frame) + return false; + Page* page = frame->page(); + if (!page) + return false; + return page->chrome()->canRunModal(); +} + +bool DOMWindow::canShowModalDialogNow(const Frame* frame) +{ + if (!frame) + return false; + Page* page = frame->page(); + if (!page) + return false; + return page->chrome()->canRunModalNow(); +} + DOMWindow::DOMWindow(Frame* frame) : m_frame(frame) { @@ -151,6 +359,14 @@ DOMWindow::~DOMWindow() { if (m_frame) m_frame->clearFormerDOMWindow(this); + + removePendingEventListeners(pendingUnloadEventListenerMap(), this); + removePendingEventListeners(pendingBeforeUnloadEventListenerMap(), this); +} + +ScriptExecutionContext* DOMWindow::scriptExecutionContext() const +{ + return document(); } void DOMWindow::disconnectFrame() @@ -323,10 +539,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(); } @@ -349,9 +565,11 @@ Storage* DOMWindow::localStorage() const return 0; LocalStorage* localStorage = page->group().localStorage(); - RefPtr<StorageArea> storageArea = localStorage ? localStorage->storageArea(m_frame, document->securityOrigin()) : 0; - if (storageArea) + RefPtr<StorageArea> storageArea = localStorage ? localStorage->storageArea(document->securityOrigin()) : 0; + if (storageArea) { + page->inspectorController()->didUseDOMStorage(storageArea.get(), true, m_frame); m_localStorage = Storage::create(m_frame, storageArea.release()); + } return m_localStorage.get(); } @@ -366,7 +584,7 @@ void DOMWindow::postMessage(const String& message, MessagePort* messagePort, con // to generate the SYNTAX_ERR exception correctly. RefPtr<SecurityOrigin> target; if (targetOrigin != "*") { - target = SecurityOrigin::create(KURL(targetOrigin)); + target = SecurityOrigin::createFromString(targetOrigin); if (target->isEmpty()) { ec = SYNTAX_ERR; return; @@ -413,7 +631,8 @@ void DOMWindow::postMessageTimerFired(PostMessageTimer* t) if (messagePort) messagePort->attachToContext(document()); - document()->dispatchWindowEvent(timer->event()); + ExceptionCode ec = 0; + dispatchEvent(timer->event(), ec); } DOMSelection* DOMWindow::getSelection() @@ -452,7 +671,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(); } @@ -483,10 +715,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()->updateStyleIfNeeded(); Page* page = m_frame->page(); if (!page) @@ -500,10 +729,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()->updateStyleIfNeeded(); Page* page = m_frame->page(); if (!page) @@ -517,10 +743,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()->updateStyleIfNeeded(); Page* page = m_frame->page(); if (!page) @@ -628,10 +851,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()); } @@ -645,10 +865,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()); } @@ -760,9 +977,15 @@ DOMWindow* DOMWindow::top() const Document* DOMWindow::document() const { + // FIXME: This function shouldn't need a frame to work. if (!m_frame) return 0; + // The m_frame pointer is not zeroed out when the window is put into b/f cache, so it can hold an unrelated document/window pair. + // FIXME: We should always zero out the frame pointer on navigation to avoid accidentally accessing the new frame content. + if (m_frame->domWindow() != this) + return 0; + ASSERT(m_frame->document()); return m_frame->document(); } @@ -782,15 +1005,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) @@ -810,9 +1050,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()) @@ -827,10 +1064,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) @@ -844,10 +1078,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) @@ -938,310 +1169,832 @@ void DOMWindow::resizeTo(float width, float height) const page->chrome()->setWindowRect(fr); } -inline void DOMWindow::setInlineEventListenerForType(const AtomicString& eventType, PassRefPtr<EventListener> eventListener) +int DOMWindow::setTimeout(ScheduledAction* action, int timeout) { - Document* document = this->document(); - if (!document) + return DOMTimer::install(scriptExecutionContext(), action, timeout, true); +} + +void DOMWindow::clearTimeout(int timeoutId) +{ + DOMTimer::removeById(scriptExecutionContext(), timeoutId); +} + +int DOMWindow::setInterval(ScheduledAction* action, int timeout) +{ + return DOMTimer::install(scriptExecutionContext(), action, timeout, false); +} + +void DOMWindow::clearInterval(int timeoutId) +{ + DOMTimer::removeById(scriptExecutionContext(), timeoutId); +} + +void DOMWindow::handleEvent(Event* event, bool useCapture, RegisteredEventListenerVector* alternateListeners) +{ + RegisteredEventListenerVector& listeners = (alternateListeners ? *alternateListeners : m_eventListeners); + if (listeners.isEmpty()) return; - document->setWindowInlineEventListenerForType(eventType, eventListener); + + // If any HTML event listeners are registered on the window, dispatch them here. + RegisteredEventListenerVector listenersCopy = listeners; + size_t size = listenersCopy.size(); + for (size_t i = 0; i < size; ++i) { + RegisteredEventListener& r = *listenersCopy[i]; + if (r.eventType() == event->type() && r.useCapture() == useCapture && !r.removed()) + r.listener()->handleEvent(event, true); + } } -inline EventListener* DOMWindow::inlineEventListenerForType(const AtomicString& eventType) const +void DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) { - Document* document = this->document(); - if (!document) - return 0; - return document->windowInlineEventListenerForType(eventType); + // Remove existing identical listener set with identical arguments. + // The DOM 2 spec says that "duplicate instances are discarded" in this case. + removeEventListener(eventType, listener.get(), useCapture); + if (Document* document = this->document()) + document->addListenerTypeIfNeeded(eventType); + + RefPtr<RegisteredEventListener> registeredListener = RegisteredEventListener::create(eventType, listener, useCapture); + m_eventListeners.append(registeredListener); + + if (eventType == eventNames().unloadEvent) + addPendingEventListener(pendingUnloadEventListenerMap(), this, registeredListener.get()); + else if (eventType == eventNames().beforeunloadEvent && allowsPendingBeforeUnloadListeners(this)) + addPendingEventListener(pendingBeforeUnloadEventListenerMap(), this, registeredListener.get()); +} + +void DOMWindow::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) +{ + size_t size = m_eventListeners.size(); + for (size_t i = 0; i < size; ++i) { + RegisteredEventListener& r = *m_eventListeners[i]; + if (r.eventType() == eventType && r.listener() == listener && r.useCapture() == useCapture) { + if (eventType == eventNames().unloadEvent) + removePendingEventListener(pendingUnloadEventListenerMap(), this, &r); + else if (eventType == eventNames().beforeunloadEvent && allowsPendingBeforeUnloadListeners(this)) + removePendingEventListener(pendingBeforeUnloadEventListenerMap(), this, &r); + r.setRemoved(true); + m_eventListeners.remove(i); + return; + } + } +} + +bool DOMWindow::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec) +{ + ASSERT(!eventDispatchForbidden()); + + RefPtr<Event> event = e; + if (!event || event->type().isEmpty()) { + ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; + return true; + } + + RefPtr<DOMWindow> protect(this); + + event->setTarget(this); + event->setCurrentTarget(this); + + handleEvent(event.get(), true); + handleEvent(event.get(), false); + + return !event->defaultPrevented(); +} + +void DOMWindow::dispatchEvent(const AtomicString& eventType, bool canBubble, bool cancelable) +{ + ASSERT(!eventDispatchForbidden()); + ExceptionCode ec = 0; + dispatchEvent(Event::create(eventType, canBubble, cancelable), ec); +} + +// This function accommodates the Firefox quirk of dispatching the load, unload and +// beforeunload events on the window, but setting event.target to be the Document. +inline void DOMWindow::dispatchEventWithDocumentAsTarget(PassRefPtr<Event> e, RegisteredEventListenerVector* alternateEventListeners) +{ + ASSERT(!eventDispatchForbidden()); + + RefPtr<Event> event = e; + RefPtr<DOMWindow> protect(this); + RefPtr<Document> document = this->document(); + + event->setTarget(document); + event->setCurrentTarget(this); + + handleEvent(event.get(), true, alternateEventListeners); + handleEvent(event.get(), false, alternateEventListeners); +} + +void DOMWindow::dispatchLoadEvent() +{ + dispatchEventWithDocumentAsTarget(Event::create(eventNames().loadEvent, false, false)); + + // For load events, send a separate load event to the enclosing frame only. + // This is a DOM extension and is independent of bubbling/capturing rules of + // the DOM. + Element* ownerElement = document()->ownerElement(); + if (ownerElement) { + RefPtr<Event> ownerEvent = Event::create(eventNames().loadEvent, false, false); + ownerEvent->setTarget(ownerElement); + ownerElement->dispatchGenericEvent(ownerEvent.release()); + } +} + +void DOMWindow::dispatchUnloadEvent(RegisteredEventListenerVector* alternateEventListeners) +{ + dispatchEventWithDocumentAsTarget(Event::create(eventNames().unloadEvent, false, false), alternateEventListeners); +} + +PassRefPtr<BeforeUnloadEvent> DOMWindow::dispatchBeforeUnloadEvent(RegisteredEventListenerVector* alternateEventListeners) +{ + RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create(); + dispatchEventWithDocumentAsTarget(beforeUnloadEvent.get(), alternateEventListeners); + return beforeUnloadEvent.release(); +} + +void DOMWindow::removeAllEventListeners() +{ + size_t size = m_eventListeners.size(); + for (size_t i = 0; i < size; ++i) + m_eventListeners[i]->setRemoved(true); + m_eventListeners.clear(); + + removePendingEventListeners(pendingUnloadEventListenerMap(), this); + removePendingEventListeners(pendingBeforeUnloadEventListenerMap(), this); +} + +bool DOMWindow::hasEventListener(const AtomicString& eventType) +{ + size_t size = m_eventListeners.size(); + for (size_t i = 0; i < size; ++i) { + if (m_eventListeners[i]->eventType() == eventType) + return true; + } + return false; +} + +void DOMWindow::setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener) +{ + clearAttributeEventListener(eventType); + if (listener) + addEventListener(eventType, listener, false); +} + +void DOMWindow::clearAttributeEventListener(const AtomicString& eventType) +{ + size_t size = m_eventListeners.size(); + for (size_t i = 0; i < size; ++i) { + RegisteredEventListener& r = *m_eventListeners[i]; + if (r.eventType() == eventType && r.listener()->isAttribute()) { + if (eventType == eventNames().unloadEvent) + removePendingEventListener(pendingUnloadEventListenerMap(), this, &r); + else if (eventType == eventNames().beforeunloadEvent && allowsPendingBeforeUnloadListeners(this)) + removePendingEventListener(pendingBeforeUnloadEventListenerMap(), this, &r); + r.setRemoved(true); + m_eventListeners.remove(i); + return; + } + } +} + +EventListener* DOMWindow::getAttributeEventListener(const AtomicString& eventType) const +{ + size_t size = m_eventListeners.size(); + for (size_t i = 0; i < size; ++i) { + RegisteredEventListener& r = *m_eventListeners[i]; + if (r.eventType() == eventType && r.listener()->isAttribute()) + return r.listener(); + } + return 0; } EventListener* DOMWindow::onabort() const { - return inlineEventListenerForType(eventNames().abortEvent); + return getAttributeEventListener(eventNames().abortEvent); } void DOMWindow::setOnabort(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().abortEvent, eventListener); + setAttributeEventListener(eventNames().abortEvent, eventListener); } EventListener* DOMWindow::onblur() const { - return inlineEventListenerForType(eventNames().blurEvent); + return getAttributeEventListener(eventNames().blurEvent); } void DOMWindow::setOnblur(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().blurEvent, eventListener); + setAttributeEventListener(eventNames().blurEvent, eventListener); } EventListener* DOMWindow::onchange() const { - return inlineEventListenerForType(eventNames().changeEvent); + return getAttributeEventListener(eventNames().changeEvent); } void DOMWindow::setOnchange(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().changeEvent, eventListener); + setAttributeEventListener(eventNames().changeEvent, eventListener); } EventListener* DOMWindow::onclick() const { - return inlineEventListenerForType(eventNames().clickEvent); + return getAttributeEventListener(eventNames().clickEvent); } void DOMWindow::setOnclick(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().clickEvent, eventListener); + setAttributeEventListener(eventNames().clickEvent, eventListener); } EventListener* DOMWindow::ondblclick() const { - return inlineEventListenerForType(eventNames().dblclickEvent); + return getAttributeEventListener(eventNames().dblclickEvent); } void DOMWindow::setOndblclick(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().dblclickEvent, eventListener); + setAttributeEventListener(eventNames().dblclickEvent, eventListener); +} + +EventListener* DOMWindow::ondrag() const +{ + return getAttributeEventListener(eventNames().dragEvent); +} + +void DOMWindow::setOndrag(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().dragEvent, eventListener); +} + +EventListener* DOMWindow::ondragend() const +{ + return getAttributeEventListener(eventNames().dragendEvent); +} + +void DOMWindow::setOndragend(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().dragendEvent, eventListener); +} + +EventListener* DOMWindow::ondragenter() const +{ + return getAttributeEventListener(eventNames().dragenterEvent); +} + +void DOMWindow::setOndragenter(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().dragenterEvent, eventListener); +} + +EventListener* DOMWindow::ondragleave() const +{ + return getAttributeEventListener(eventNames().dragleaveEvent); +} + +void DOMWindow::setOndragleave(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().dragleaveEvent, eventListener); +} + +EventListener* DOMWindow::ondragover() const +{ + return getAttributeEventListener(eventNames().dragoverEvent); +} + +void DOMWindow::setOndragover(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().dragoverEvent, eventListener); +} + +EventListener* DOMWindow::ondragstart() const +{ + return getAttributeEventListener(eventNames().dragstartEvent); +} + +void DOMWindow::setOndragstart(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().dragstartEvent, eventListener); +} + +EventListener* DOMWindow::ondrop() const +{ + return getAttributeEventListener(eventNames().dropEvent); +} + +void DOMWindow::setOndrop(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().dropEvent, eventListener); } EventListener* DOMWindow::onerror() const { - return inlineEventListenerForType(eventNames().errorEvent); + return getAttributeEventListener(eventNames().errorEvent); } void DOMWindow::setOnerror(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().errorEvent, eventListener); + setAttributeEventListener(eventNames().errorEvent, eventListener); } EventListener* DOMWindow::onfocus() const { - return inlineEventListenerForType(eventNames().focusEvent); + return getAttributeEventListener(eventNames().focusEvent); } void DOMWindow::setOnfocus(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().focusEvent, eventListener); + setAttributeEventListener(eventNames().focusEvent, eventListener); } EventListener* DOMWindow::onkeydown() const { - return inlineEventListenerForType(eventNames().keydownEvent); + return getAttributeEventListener(eventNames().keydownEvent); } void DOMWindow::setOnkeydown(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().keydownEvent, eventListener); + setAttributeEventListener(eventNames().keydownEvent, eventListener); } EventListener* DOMWindow::onkeypress() const { - return inlineEventListenerForType(eventNames().keypressEvent); + return getAttributeEventListener(eventNames().keypressEvent); } void DOMWindow::setOnkeypress(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().keypressEvent, eventListener); + setAttributeEventListener(eventNames().keypressEvent, eventListener); } EventListener* DOMWindow::onkeyup() const { - return inlineEventListenerForType(eventNames().keyupEvent); + return getAttributeEventListener(eventNames().keyupEvent); } void DOMWindow::setOnkeyup(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().keyupEvent, eventListener); + setAttributeEventListener(eventNames().keyupEvent, eventListener); } EventListener* DOMWindow::onload() const { - return inlineEventListenerForType(eventNames().loadEvent); + return getAttributeEventListener(eventNames().loadEvent); } void DOMWindow::setOnload(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().loadEvent, eventListener); + setAttributeEventListener(eventNames().loadEvent, eventListener); } EventListener* DOMWindow::onmousedown() const { - return inlineEventListenerForType(eventNames().mousedownEvent); + return getAttributeEventListener(eventNames().mousedownEvent); } void DOMWindow::setOnmousedown(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().mousedownEvent, eventListener); + setAttributeEventListener(eventNames().mousedownEvent, eventListener); } EventListener* DOMWindow::onmousemove() const { - return inlineEventListenerForType(eventNames().mousemoveEvent); + return getAttributeEventListener(eventNames().mousemoveEvent); } void DOMWindow::setOnmousemove(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().mousemoveEvent, eventListener); + setAttributeEventListener(eventNames().mousemoveEvent, eventListener); } EventListener* DOMWindow::onmouseout() const { - return inlineEventListenerForType(eventNames().mouseoutEvent); + return getAttributeEventListener(eventNames().mouseoutEvent); } void DOMWindow::setOnmouseout(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().mouseoutEvent, eventListener); + setAttributeEventListener(eventNames().mouseoutEvent, eventListener); } EventListener* DOMWindow::onmouseover() const { - return inlineEventListenerForType(eventNames().mouseoverEvent); + return getAttributeEventListener(eventNames().mouseoverEvent); } void DOMWindow::setOnmouseover(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().mouseoverEvent, eventListener); + setAttributeEventListener(eventNames().mouseoverEvent, eventListener); } EventListener* DOMWindow::onmouseup() const { - return inlineEventListenerForType(eventNames().mouseupEvent); + return getAttributeEventListener(eventNames().mouseupEvent); } void DOMWindow::setOnmouseup(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().mouseupEvent, eventListener); + setAttributeEventListener(eventNames().mouseupEvent, eventListener); } EventListener* DOMWindow::onmousewheel() const { - return inlineEventListenerForType(eventNames().mousewheelEvent); + return getAttributeEventListener(eventNames().mousewheelEvent); } void DOMWindow::setOnmousewheel(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().mousewheelEvent, eventListener); + setAttributeEventListener(eventNames().mousewheelEvent, eventListener); +} + +EventListener* DOMWindow::onoffline() const +{ + return getAttributeEventListener(eventNames().offlineEvent); +} + +void DOMWindow::setOnoffline(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().offlineEvent, eventListener); +} + +EventListener* DOMWindow::ononline() const +{ + return getAttributeEventListener(eventNames().onlineEvent); +} + +void DOMWindow::setOnonline(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().onlineEvent, eventListener); } EventListener* DOMWindow::onreset() const { - return inlineEventListenerForType(eventNames().resetEvent); + return getAttributeEventListener(eventNames().resetEvent); } void DOMWindow::setOnreset(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().resetEvent, eventListener); + setAttributeEventListener(eventNames().resetEvent, eventListener); } EventListener* DOMWindow::onresize() const { - return inlineEventListenerForType(eventNames().resizeEvent); + return getAttributeEventListener(eventNames().resizeEvent); } void DOMWindow::setOnresize(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().resizeEvent, eventListener); + setAttributeEventListener(eventNames().resizeEvent, eventListener); } EventListener* DOMWindow::onscroll() const { - return inlineEventListenerForType(eventNames().scrollEvent); + return getAttributeEventListener(eventNames().scrollEvent); } void DOMWindow::setOnscroll(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().scrollEvent, eventListener); + setAttributeEventListener(eventNames().scrollEvent, eventListener); } EventListener* DOMWindow::onsearch() const { - return inlineEventListenerForType(eventNames().searchEvent); + return getAttributeEventListener(eventNames().searchEvent); } void DOMWindow::setOnsearch(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().searchEvent, eventListener); + setAttributeEventListener(eventNames().searchEvent, eventListener); } EventListener* DOMWindow::onselect() const { - return inlineEventListenerForType(eventNames().selectEvent); + return getAttributeEventListener(eventNames().selectEvent); } void DOMWindow::setOnselect(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().selectEvent, eventListener); + setAttributeEventListener(eventNames().selectEvent, eventListener); +} + +EventListener* DOMWindow::onstorage() const +{ + return getAttributeEventListener(eventNames().storageEvent); +} + +void DOMWindow::setOnstorage(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().storageEvent, eventListener); } EventListener* DOMWindow::onsubmit() const { - return inlineEventListenerForType(eventNames().submitEvent); + return getAttributeEventListener(eventNames().submitEvent); } void DOMWindow::setOnsubmit(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().submitEvent, eventListener); + setAttributeEventListener(eventNames().submitEvent, eventListener); } EventListener* DOMWindow::onunload() const { - return inlineEventListenerForType(eventNames().unloadEvent); + return getAttributeEventListener(eventNames().unloadEvent); } void DOMWindow::setOnunload(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().unloadEvent, eventListener); + setAttributeEventListener(eventNames().unloadEvent, eventListener); } EventListener* DOMWindow::onbeforeunload() const { - return inlineEventListenerForType(eventNames().beforeunloadEvent); + return getAttributeEventListener(eventNames().beforeunloadEvent); } void DOMWindow::setOnbeforeunload(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().beforeunloadEvent, eventListener); + setAttributeEventListener(eventNames().beforeunloadEvent, eventListener); } EventListener* DOMWindow::onwebkitanimationstart() const { - return inlineEventListenerForType(eventNames().webkitAnimationStartEvent); + return getAttributeEventListener(eventNames().webkitAnimationStartEvent); } void DOMWindow::setOnwebkitanimationstart(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().webkitAnimationStartEvent, eventListener); + setAttributeEventListener(eventNames().webkitAnimationStartEvent, eventListener); } EventListener* DOMWindow::onwebkitanimationiteration() const { - return inlineEventListenerForType(eventNames().webkitAnimationIterationEvent); + return getAttributeEventListener(eventNames().webkitAnimationIterationEvent); } void DOMWindow::setOnwebkitanimationiteration(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().webkitAnimationIterationEvent, eventListener); + setAttributeEventListener(eventNames().webkitAnimationIterationEvent, eventListener); } EventListener* DOMWindow::onwebkitanimationend() const { - return inlineEventListenerForType(eventNames().webkitAnimationEndEvent); + return getAttributeEventListener(eventNames().webkitAnimationEndEvent); } void DOMWindow::setOnwebkitanimationend(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().webkitAnimationEndEvent, eventListener); + setAttributeEventListener(eventNames().webkitAnimationEndEvent, eventListener); } EventListener* DOMWindow::onwebkittransitionend() const { - return inlineEventListenerForType(eventNames().webkitTransitionEndEvent); + return getAttributeEventListener(eventNames().webkitTransitionEndEvent); } void DOMWindow::setOnwebkittransitionend(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().webkitTransitionEndEvent, eventListener); + setAttributeEventListener(eventNames().webkitTransitionEndEvent, eventListener); +} + +EventListener* DOMWindow::oncanplay() const +{ + return getAttributeEventListener(eventNames().canplayEvent); +} + +void DOMWindow::setOncanplay(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().canplayEvent, eventListener); +} + +EventListener* DOMWindow::oncanplaythrough() const +{ + return getAttributeEventListener(eventNames().canplaythroughEvent); +} + +void DOMWindow::setOncanplaythrough(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().canplaythroughEvent, eventListener); +} + +EventListener* DOMWindow::ondurationchange() const +{ + return getAttributeEventListener(eventNames().durationchangeEvent); +} + +void DOMWindow::setOndurationchange(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().durationchangeEvent, eventListener); +} + +EventListener* DOMWindow::onemptied() const +{ + return getAttributeEventListener(eventNames().emptiedEvent); +} + +void DOMWindow::setOnemptied(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().emptiedEvent, eventListener); +} + +EventListener* DOMWindow::onended() const +{ + return getAttributeEventListener(eventNames().endedEvent); +} + +void DOMWindow::setOnended(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().endedEvent, eventListener); +} + +EventListener* DOMWindow::onloadeddata() const +{ + return getAttributeEventListener(eventNames().loadeddataEvent); +} + +void DOMWindow::setOnloadeddata(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().loadeddataEvent, eventListener); +} + +EventListener* DOMWindow::onloadedmetadata() const +{ + return getAttributeEventListener(eventNames().loadedmetadataEvent); +} + +void DOMWindow::setOnloadedmetadata(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().loadedmetadataEvent, eventListener); +} + +EventListener* DOMWindow::onpause() const +{ + return getAttributeEventListener(eventNames().pauseEvent); +} + +void DOMWindow::setOnpause(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().pauseEvent, eventListener); +} + +EventListener* DOMWindow::onplay() const +{ + return getAttributeEventListener(eventNames().playEvent); +} + +void DOMWindow::setOnplay(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().playEvent, eventListener); +} + +EventListener* DOMWindow::onplaying() const +{ + return getAttributeEventListener(eventNames().playingEvent); +} + +void DOMWindow::setOnplaying(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().playingEvent, eventListener); +} + +EventListener* DOMWindow::onratechange() const +{ + return getAttributeEventListener(eventNames().ratechangeEvent); +} + +void DOMWindow::setOnratechange(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().ratechangeEvent, eventListener); +} + +EventListener* DOMWindow::onseeked() const +{ + return getAttributeEventListener(eventNames().seekedEvent); +} + +void DOMWindow::setOnseeked(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().seekedEvent, eventListener); +} + +EventListener* DOMWindow::onseeking() const +{ + return getAttributeEventListener(eventNames().seekingEvent); +} + +void DOMWindow::setOnseeking(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().seekingEvent, eventListener); +} + +EventListener* DOMWindow::ontimeupdate() const +{ + return getAttributeEventListener(eventNames().timeupdateEvent); +} + +void DOMWindow::setOntimeupdate(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().timeupdateEvent, eventListener); +} + +EventListener* DOMWindow::onvolumechange() const +{ + return getAttributeEventListener(eventNames().volumechangeEvent); +} + +void DOMWindow::setOnvolumechange(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().volumechangeEvent, eventListener); +} + +EventListener* DOMWindow::onwaiting() const +{ + return getAttributeEventListener(eventNames().waitingEvent); +} + +void DOMWindow::setOnwaiting(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().waitingEvent, eventListener); +} + +EventListener* DOMWindow::onloadstart() const +{ + return getAttributeEventListener(eventNames().loadstartEvent); +} + +void DOMWindow::setOnloadstart(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().loadstartEvent, eventListener); +} + +EventListener* DOMWindow::onprogress() const +{ + return getAttributeEventListener(eventNames().progressEvent); +} + +void DOMWindow::setOnprogress(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().progressEvent, eventListener); +} + +EventListener* DOMWindow::onstalled() const +{ + return getAttributeEventListener(eventNames().stalledEvent); +} + +void DOMWindow::setOnstalled(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().stalledEvent, eventListener); +} + +EventListener* DOMWindow::onsuspend() const +{ + return getAttributeEventListener(eventNames().suspendEvent); +} + +void DOMWindow::setOnsuspend(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().suspendEvent, eventListener); +} + +EventListener* DOMWindow::oninput() const +{ + return getAttributeEventListener(eventNames().inputEvent); +} + +void DOMWindow::setOninput(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().inputEvent, eventListener); +} + +EventListener* DOMWindow::onmessage() const +{ + return getAttributeEventListener(eventNames().messageEvent); +} + +void DOMWindow::setOnmessage(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().messageEvent, eventListener); +} + +EventListener* DOMWindow::oncontextmenu() const +{ + return getAttributeEventListener(eventNames().contextmenuEvent); +} + +void DOMWindow::setOncontextmenu(PassRefPtr<EventListener> eventListener) +{ + setAttributeEventListener(eventNames().contextmenuEvent, eventListener); +} + +void DOMWindow::captureEvents() +{ + // Not implemented. +} + +void DOMWindow::releaseEvents() +{ + // Not implemented. } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/DOMWindow.h b/src/3rdparty/webkit/WebCore/page/DOMWindow.h index e7fab18..6862cdc 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMWindow.h +++ b/src/3rdparty/webkit/WebCore/page/DOMWindow.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 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 @@ #ifndef DOMWindow_h #define DOMWindow_h +#include "EventTarget.h" #include "KURL.h" #include "PlatformString.h" +#include "RegisteredEventListener.h" #include "SecurityOrigin.h" #include <wtf/Forward.h> #include <wtf/RefCounted.h> @@ -36,6 +38,7 @@ namespace WebCore { class BarInfo; + class BeforeUnloadEvent; class CSSRuleList; class CSSStyleDeclaration; class Console; @@ -43,6 +46,7 @@ namespace WebCore { class Database; class Document; class Element; + class Event; class EventListener; class FloatRect; class Frame; @@ -50,8 +54,11 @@ namespace WebCore { class Location; class MessagePort; class Navigator; + class Node; class PostMessageTimer; + class ScheduledAction; class Screen; + class WebKitPoint; #if ENABLE(DOM_STORAGE) class SessionStorage; @@ -64,12 +71,15 @@ namespace WebCore { typedef int ExceptionCode; - class DOMWindow : public RefCounted<DOMWindow> { + class DOMWindow : public RefCounted<DOMWindow>, public EventTarget { public: static PassRefPtr<DOMWindow> create(Frame* frame) { return adoptRef(new DOMWindow(frame)); } virtual ~DOMWindow(); - Frame* frame() { return m_frame; } + virtual DOMWindow* toDOMWindow() { return this; } + virtual ScriptExecutionContext* scriptExecutionContext() const; + + Frame* frame() const { return m_frame; } void disconnectFrame(); void clear(); @@ -80,7 +90,17 @@ namespace WebCore { void setURL(const KURL& url) { m_url = url; } KURL url() const { return m_url; } + unsigned pendingUnloadEventListeners() const; + + static bool dispatchAllPendingBeforeUnloadEvents(); + static void dispatchAllPendingUnloadEvents(); + static void adjustWindowRect(const FloatRect& screen, FloatRect& window, const FloatRect& pendingChanges); + static void parseModalDialogFeatures(const String& featuresArg, HashMap<String, String>& map); + + static bool allowPopUp(Frame* activeFrame); + static bool canShowModalDialog(const Frame*); + static bool canShowModalDialogNow(const Frame*); // DOM Level 0 Screen* screen() const; @@ -160,6 +180,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&); @@ -190,6 +213,34 @@ namespace WebCore { void resizeBy(float x, float y) const; void resizeTo(float width, float height) const; + // Timers + int setTimeout(ScheduledAction*, int timeout); + void clearTimeout(int timeoutId); + int setInterval(ScheduledAction*, int timeout); + void clearInterval(int timeoutId); + + // Events + // EventTarget API + virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); + virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); + virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); + + void handleEvent(Event*, bool useCapture, RegisteredEventListenerVector* = 0); + + void dispatchEvent(const AtomicString& eventType, bool canBubble, bool cancelable); + void dispatchLoadEvent(); + void dispatchUnloadEvent(RegisteredEventListenerVector* = 0); + PassRefPtr<BeforeUnloadEvent> dispatchBeforeUnloadEvent(RegisteredEventListenerVector* = 0); + + // Used for legacy "onEvent" property APIs. + void setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>); + void clearAttributeEventListener(const AtomicString& eventType); + EventListener* getAttributeEventListener(const AtomicString& eventType) const; + + const RegisteredEventListenerVector& eventListeners() const { return m_eventListeners; } + bool hasEventListener(const AtomicString& eventType); + void removeAllEventListeners(); + EventListener* onabort() const; void setOnabort(PassRefPtr<EventListener>); EventListener* onblur() const; @@ -200,6 +251,20 @@ namespace WebCore { void setOnclick(PassRefPtr<EventListener>); EventListener* ondblclick() const; void setOndblclick(PassRefPtr<EventListener>); + EventListener* ondrag() const; + void setOndrag(PassRefPtr<EventListener>); + EventListener* ondragend() const; + void setOndragend(PassRefPtr<EventListener>); + EventListener* ondragenter() const; + void setOndragenter(PassRefPtr<EventListener>); + EventListener* ondragleave() const; + void setOndragleave(PassRefPtr<EventListener>); + EventListener* ondragover() const; + void setOndragover(PassRefPtr<EventListener>); + EventListener* ondragstart() const; + void setOndragstart(PassRefPtr<EventListener>); + EventListener* ondrop() const; + void setOndrop(PassRefPtr<EventListener>); EventListener* onerror() const; void setOnerror(PassRefPtr<EventListener>); EventListener* onfocus() const; @@ -224,6 +289,10 @@ namespace WebCore { void setOnmouseup(PassRefPtr<EventListener>); EventListener* onmousewheel() const; void setOnmousewheel(PassRefPtr<EventListener>); + EventListener* onoffline() const; + void setOnoffline(PassRefPtr<EventListener>); + EventListener* ononline() const; + void setOnonline(PassRefPtr<EventListener>); EventListener* onreset() const; void setOnreset(PassRefPtr<EventListener>); EventListener* onresize() const; @@ -234,6 +303,8 @@ namespace WebCore { void setOnsearch(PassRefPtr<EventListener>); EventListener* onselect() const; void setOnselect(PassRefPtr<EventListener>); + EventListener* onstorage() const; + void setOnstorage(PassRefPtr<EventListener>); EventListener* onsubmit() const; void setOnsubmit(PassRefPtr<EventListener>); EventListener* onunload() const; @@ -248,6 +319,55 @@ namespace WebCore { void setOnwebkitanimationend(PassRefPtr<EventListener>); EventListener* onwebkittransitionend() const; void setOnwebkittransitionend(PassRefPtr<EventListener>); + EventListener* oncanplay() const; + void setOncanplay(PassRefPtr<EventListener>); + EventListener* oncanplaythrough() const; + void setOncanplaythrough(PassRefPtr<EventListener>); + EventListener* ondurationchange() const; + void setOndurationchange(PassRefPtr<EventListener>); + EventListener* onemptied() const; + void setOnemptied(PassRefPtr<EventListener>); + EventListener* onended() const; + void setOnended(PassRefPtr<EventListener>); + EventListener* onloadeddata() const; + void setOnloadeddata(PassRefPtr<EventListener>); + EventListener* onloadedmetadata() const; + void setOnloadedmetadata(PassRefPtr<EventListener>); + EventListener* onpause() const; + void setOnpause(PassRefPtr<EventListener>); + EventListener* onplay() const; + void setOnplay(PassRefPtr<EventListener>); + EventListener* onplaying() const; + void setOnplaying(PassRefPtr<EventListener>); + EventListener* onratechange() const; + void setOnratechange(PassRefPtr<EventListener>); + EventListener* onseeked() const; + void setOnseeked(PassRefPtr<EventListener>); + EventListener* onseeking() const; + void setOnseeking(PassRefPtr<EventListener>); + EventListener* ontimeupdate() const; + void setOntimeupdate(PassRefPtr<EventListener>); + EventListener* onvolumechange() const; + void setOnvolumechange(PassRefPtr<EventListener>); + EventListener* onwaiting() const; + void setOnwaiting(PassRefPtr<EventListener>); + EventListener* onloadstart() const; + void setOnloadstart(PassRefPtr<EventListener>); + EventListener* onprogress() const; + void setOnprogress(PassRefPtr<EventListener>); + EventListener* onstalled() const; + void setOnstalled(PassRefPtr<EventListener>); + EventListener* onsuspend() const; + void setOnsuspend(PassRefPtr<EventListener>); + EventListener* oninput() const; + void setOninput(PassRefPtr<EventListener>); + EventListener* onmessage() const; + void setOnmessage(PassRefPtr<EventListener>); + EventListener* oncontextmenu() const; + void setOncontextmenu(PassRefPtr<EventListener>); + + void captureEvents(); + void releaseEvents(); // These methods are used for GC marking. See JSDOMWindow::mark() in // JSDOMWindowCustom.cpp. @@ -271,11 +391,16 @@ namespace WebCore { DOMApplicationCache* optionalApplicationCache() const { return m_applicationCache.get(); } #endif + using RefCounted<DOMWindow>::ref; + using RefCounted<DOMWindow>::deref; + private: DOMWindow(Frame*); - void setInlineEventListenerForType(const AtomicString& eventType, PassRefPtr<EventListener>); - EventListener* inlineEventListenerForType(const AtomicString& eventType) const; + virtual void refEventTarget() { ref(); } + virtual void derefEventTarget() { deref(); } + + void dispatchEventWithDocumentAsTarget(PassRefPtr<Event>, RegisteredEventListenerVector* = 0); RefPtr<SecurityOrigin> m_securityOrigin; KURL m_url; @@ -300,8 +425,10 @@ namespace WebCore { #if ENABLE(OFFLINE_WEB_APPLICATIONS) mutable RefPtr<DOMApplicationCache> m_applicationCache; #endif + + RegisteredEventListenerVector m_eventListeners; }; } // namespace WebCore -#endif +#endif // DOMWindow_h diff --git a/src/3rdparty/webkit/WebCore/page/DOMWindow.idl b/src/3rdparty/webkit/WebCore/page/DOMWindow.idl index 504b705..67ce3802 100644 --- a/src/3rdparty/webkit/WebCore/page/DOMWindow.idl +++ b/src/3rdparty/webkit/WebCore/page/DOMWindow.idl @@ -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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,7 +44,7 @@ module window { ] DOMWindow { // DOM Level 0 readonly attribute Screen screen; - readonly attribute [DoNotCheckDomainSecurity] History history; + readonly attribute [DoNotCheckDomainSecurity, JSCCustomGetter] History history; attribute [Replaceable] BarInfo locationbar; attribute [Replaceable] BarInfo menubar; attribute [Replaceable] BarInfo personalbar; @@ -53,7 +53,11 @@ module window { attribute [Replaceable] BarInfo toolbar; attribute [Replaceable] Navigator navigator; attribute [Replaceable] Navigator clientInformation; - attribute [DoNotCheckDomainSecurity, CustomSetter] Location location; + attribute [DoNotCheckDomainSecurity, JSCCustom, V8CustomSetter, V8DisallowShadowing] Location location; + + attribute [Replaceable, CustomGetter] Event event; + + readonly attribute [Custom] Crypto crypto; DOMSelection getSelection(); @@ -66,6 +70,14 @@ module window { void print(); void stop(); + [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); + void alert(in DOMString message); boolean confirm(in DOMString message); [ConvertNullStringTo=Null] DOMString prompt(in DOMString message, @@ -110,19 +122,19 @@ module window { attribute DOMString status; attribute DOMString defaultStatus; -#if defined(LANGUAGE_JAVASCRIPT) +#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT // This attribute is an alias of defaultStatus and is necessary for legacy uses. attribute DOMString defaultstatus; #endif // 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; @@ -136,15 +148,18 @@ 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 +#if defined(ENABLE_OFFLINE_WEB_APPLICATIONS) && ENABLE_OFFLINE_WEB_APPLICATIONS readonly attribute DOMApplicationCache applicationCache; #endif -#if ENABLE_DATABASE +#if defined(ENABLE_DATABASE) && ENABLE_DATABASE Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize) raises(DOMException); #endif -#if ENABLE_DOM_STORAGE +#if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE readonly attribute Storage sessionStorage; readonly attribute Storage localStorage; #endif @@ -157,12 +172,13 @@ module window { // Timers [Custom] long setTimeout(in TimeoutHandler handler, in long timeout); + // [Custom] long setTimeout(in TimeoutHandler handler, in long timeout, arguments...); // [Custom] long setTimeout(in DOMString code, in long timeout); - [Custom] void clearTimeout(in long handle); - + void clearTimeout(in long handle); [Custom] long setInterval(in TimeoutHandler handler, in long timeout); + // [Custom] long setInterval(in TimeoutHandler handler, in long timeout, arguments...); // [Custom] long setInterval(in DOMString code, in long timeout); - [Custom] void clearInterval(in long handle); + void clearInterval(in long handle); // Base64 [Custom] DOMString atob(in DOMString string) @@ -171,46 +187,99 @@ module window { raises(DOMException); // Events - attribute [ProtectedListener] EventListener onabort; - attribute [ProtectedListener] EventListener onblur; - attribute [ProtectedListener] EventListener onchange; - attribute [ProtectedListener] EventListener onclick; - attribute [ProtectedListener] EventListener ondblclick; - attribute [ProtectedListener] EventListener onerror; - attribute [ProtectedListener] EventListener onfocus; - attribute [ProtectedListener] EventListener onkeydown; - attribute [ProtectedListener] EventListener onkeypress; - attribute [ProtectedListener] EventListener onkeyup; - attribute [ProtectedListener] EventListener onload; - attribute [ProtectedListener] EventListener onmousedown; - attribute [ProtectedListener] EventListener onmousemove; - attribute [ProtectedListener] EventListener onmouseout; - attribute [ProtectedListener] EventListener onmouseover; - attribute [ProtectedListener] EventListener onmouseup; - attribute [ProtectedListener] EventListener onmousewheel; - attribute [ProtectedListener] EventListener onreset; - attribute [ProtectedListener] EventListener onresize; - attribute [ProtectedListener] EventListener onscroll; - attribute [ProtectedListener] EventListener onsearch; - attribute [ProtectedListener] EventListener onselect; - attribute [ProtectedListener] EventListener onsubmit; - attribute [ProtectedListener] EventListener onunload; - attribute [ProtectedListener] EventListener onbeforeunload; - attribute [ProtectedListener] EventListener onwebkitanimationstart; - attribute [ProtectedListener] EventListener onwebkitanimationiteration; - attribute [ProtectedListener] EventListener onwebkitanimationend; - attribute [ProtectedListener] EventListener onwebkittransitionend; + attribute EventListener onabort; + attribute EventListener onbeforeunload; + attribute EventListener onblur; + attribute EventListener oncanplay; + attribute EventListener oncanplaythrough; + attribute EventListener onchange; + attribute EventListener onclick; + attribute EventListener oncontextmenu; + attribute EventListener ondblclick; + attribute EventListener ondrag; + attribute EventListener ondragend; + attribute EventListener ondragenter; + attribute EventListener ondragleave; + attribute EventListener ondragover; + attribute EventListener ondragstart; + attribute EventListener ondrop; + attribute EventListener ondurationchange; + attribute EventListener onemptied; + attribute EventListener onended; + attribute EventListener onerror; + attribute EventListener onfocus; + attribute EventListener oninput; + attribute EventListener onkeydown; + attribute EventListener onkeypress; + attribute EventListener onkeyup; + attribute EventListener onload; + attribute EventListener onloadeddata; + attribute EventListener onloadedmetadata; + attribute EventListener onloadstart; + attribute EventListener onmessage; + attribute EventListener onmousedown; + attribute EventListener onmousemove; + attribute EventListener onmouseout; + attribute EventListener onmouseover; + attribute EventListener onmouseup; + attribute EventListener onmousewheel; + attribute EventListener onoffline; + attribute EventListener ononline; + attribute EventListener onpause; + attribute EventListener onplay; + attribute EventListener onplaying; + attribute EventListener onprogress; + attribute EventListener onratechange; + attribute EventListener onresize; + attribute EventListener onscroll; + attribute EventListener onseeked; + attribute EventListener onseeking; + attribute EventListener onselect; + attribute EventListener onstalled; + attribute EventListener onstorage; + attribute EventListener onsubmit; + attribute EventListener onsuspend; + attribute EventListener ontimeupdate; + attribute EventListener onunload; + attribute EventListener onvolumechange; + attribute EventListener onwaiting; + + // Not implemented yet. + // attribute EventListener onafterprint; + // attribute EventListener onbeforeprint; + // attribute EventListener ondataunavailable; + // attribute EventListener onformchange; + // attribute EventListener onforminput; + // attribute EventListener onhashchange; + // attribute EventListener oninvalid; + // attribute EventListener onpopstate; + // attribute EventListener onreadystatechange; + // attribute EventListener onredo; + // attribute EventListener onshow; + // attribute EventListener onundo; + + // Webkit extensions + attribute EventListener onreset; + attribute EventListener onsearch; + attribute EventListener onwebkitanimationend; + attribute EventListener onwebkitanimationiteration; + attribute EventListener onwebkitanimationstart; + attribute EventListener onwebkittransitionend; // 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 + boolean dispatchEvent(in Event evt) + raises(EventException); -#if defined(LANGUAGE_JAVASCRIPT) + [V8Custom=DOMWindowNOP] void captureEvents(/*in long eventFlags*/); + [V8Custom=DOMWindowNOP] void releaseEvents(/*in long eventFlags*/); + +#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT // Global constructors attribute StyleSheetConstructor StyleSheet; attribute CSSStyleSheetConstructor CSSStyleSheet; @@ -330,6 +399,9 @@ module window { attribute HTMLCollectionConstructor HTMLCollection; + attribute [CustomGetter] HTMLImageElementConstructor Image; // Usable with new operator + attribute [CustomGetter] HTMLOptionElementConstructor Option; // Usable with new operator + attribute CanvasRenderingContext2DConstructor CanvasRenderingContext2D; attribute TextMetricsConstructor TextMetrics; @@ -350,9 +422,9 @@ module window { attribute WebKitCSSKeyframeRuleConstructor WebKitCSSKeyframeRule; attribute WebKitCSSKeyframesRuleConstructor WebKitCSSKeyframesRule; -#if ENABLE_CHANNEL_MESSAGING - attribute MessagePortConstructor MessagePort; -#endif + attribute [JSCCustomGetter] WebKitCSSMatrixConstructor WebKitCSSMatrix; // Usable with the new operator + + attribute [JSCCustomGetter] WebKitPointConstructor WebKitPoint; // Usable with new the operator attribute ClipboardConstructor Clipboard; @@ -370,32 +442,50 @@ module window { attribute DOMParserConstructor DOMParser; attribute XMLSerializerConstructor XMLSerializer; + attribute [JSCCustomGetter] XMLHttpRequestConstructor XMLHttpRequest; // Usable with the new operator attribute XMLHttpRequestUploadConstructor XMLHttpRequestUpload; attribute XMLHttpRequestExceptionConstructor XMLHttpRequestException; +#if defined(ENABLE_XSLT) && ENABLE_XSLT + attribute [JSCCustomGetter] XSLTProcessorConstructor XSLTProcessor; // Usable with the new operator +#endif + +#if defined(ENABLE_CHANNEL_MESSAGING) && ENABLE_CHANNEL_MESSAGING + attribute MessagePortConstructor MessagePort; + attribute [JSCCustomGetter] MessageChannelConstructor MessageChannel; // Usable with the new operator +#endif + +#if defined(ENABLE_WORKERS) && ENABLE_WORKERS + attribute [JSCCustomGetter] WorkerConstructor Worker; // Usable with the new operator +#endif + attribute PluginConstructor Plugin; attribute PluginArrayConstructor PluginArray; attribute MimeTypeConstructor MimeType; attribute MimeTypeArrayConstructor MimeTypeArray; -#if ENABLE_DOM_STORAGE + attribute ClientRectConstructor ClientRect; + attribute ClientRectListConstructor ClientRectList; + +#if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE attribute StorageConstructor Storage; attribute StorageEventConstructor StorageEvent; #endif + attribute [CustomGetter,Conditional=VIDEO] HTMLAudioElementConstructor Audio; // Usable with the new operator attribute [Conditional=VIDEO] HTMLAudioElementConstructor HTMLAudioElement; attribute [Conditional=VIDEO] HTMLMediaElementConstructor HTMLMediaElement; attribute [Conditional=VIDEO] HTMLVideoElementConstructor HTMLVideoElement; attribute [Conditional=VIDEO] MediaErrorConstructor MediaError; -#if ENABLE_XPATH +#if defined(ENABLE_XPATH) && ENABLE_XPATH attribute XPathEvaluatorConstructor XPathEvaluator; attribute XPathResultConstructor XPathResult; attribute XPathExceptionConstructor XPathException; #endif -#if ENABLE_SVG +#if defined(ENABLE_SVG) && ENABLE_SVG attribute SVGAngleConstructor SVGAngle; attribute SVGColorConstructor SVGColor; // attribute SVGCSSRuleConstructor SVGCSSRule; @@ -412,9 +502,8 @@ module window { attribute SVGTransformConstructor SVGTransform; attribute SVGUnitTypesConstructor SVGUnitTypes; // attribute SVGZoomAndPanConstructor SVGZoomAndPan; -#endif -#if ENABLE_SVG_FILTERS +#if defined(ENABLE_FILTERS) && ENABLE_FILTERS attribute SVGComponentTransferFunctionElementConstructor SVGComponentTransferFunctionElement; attribute SVGFEBlendElementConstructor SVGFEBlendElement; attribute SVGFEColorMatrixElementConstructor SVGFEColorMatrixElement; @@ -424,8 +513,14 @@ module window { // attribute SVGFEMorphologyElementConstructor SVGFEMorphologyElement; attribute SVGFETurbulenceElementConstructor SVGFETurbulenceElement; #endif +#endif #endif // defined(LANGUAGE_JAVASCRIPT) + +#if defined(V8_BINDING) && V8_BINDING + // window.toString() requires special handling in V8 + [V8DoNotCheckSignature, DoNotCheckDomainSecurity, Custom, DontEnum] DOMString toString(); +#endif // defined(V8_BINDING) }; } diff --git a/src/3rdparty/webkit/WebCore/page/DragController.cpp b/src/3rdparty/webkit/WebCore/page/DragController.cpp index 8490f2d..e1b5ea7 100644 --- a/src/3rdparty/webkit/WebCore/page/DragController.cpp +++ b/src/3rdparty/webkit/WebCore/page/DragController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 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 @@ -57,10 +57,10 @@ #include "ResourceRequest.h" #include "SelectionController.h" #include "Settings.h" -#include "SystemTime.h" #include "Text.h" #include "htmlediting.h" #include "markup.h" +#include <wtf/CurrentTime.h> #include <wtf/RefPtr.h> namespace WebCore { @@ -76,13 +76,13 @@ static PlatformMouseEvent createMouseEvent(DragData* dragData) DragController::DragController(Page* page, DragClient* client) : m_page(page) , m_client(client) - , m_document(0) + , m_documentUnderMouse(0) , m_dragInitiator(0) , m_dragDestinationAction(DragDestinationActionNone) , m_dragSourceAction(DragSourceActionNone) , m_didInitiateDrag(false) , m_isHandlingDrag(false) - , m_dragOperation(DragOperationNone) + , m_sourceDragOperation(DragOperationNone) { } @@ -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(); @@ -126,13 +126,12 @@ static PassRefPtr<DocumentFragment> documentFragmentFromDragData(DragData* dragD return 0; } -bool DragController::dragIsMove(SelectionController* selection, DragData* dragData) +bool DragController::dragIsMove(SelectionController* selection) { - return m_document == m_dragInitiator - && selection->isContentEditable() - && !isCopyKeyDown(); + return m_documentUnderMouse == m_dragInitiator && selection->isContentEditable() && !isCopyKeyDown(); } +// FIXME: This method is poorly named. We're just clearing the selection from the document this drag is exiting. void DragController::cancelDrag() { m_page->dragCaretController()->clear(); @@ -156,16 +155,15 @@ void DragController::dragExited(DragData* dragData) Frame* mainFrame = m_page->mainFrame(); if (RefPtr<FrameView> v = mainFrame->view()) { - ClipboardAccessPolicy policy = mainFrame->loader()->baseURL().isLocalFile() ? ClipboardReadable : ClipboardTypesReadable; + ClipboardAccessPolicy policy = (!m_documentUnderMouse || m_documentUnderMouse->securityOrigin()->isLocal()) ? ClipboardReadable : ClipboardTypesReadable; RefPtr<Clipboard> clipboard = dragData->createClipboard(policy); clipboard->setSourceOperation(dragData->draggingSourceOperationMask()); mainFrame->eventHandler()->cancelDragAndDrop(createMouseEvent(dragData), clipboard.get()); clipboard->setAccessPolicy(ClipboardNumb); // invalidate clipboard here for security } - - cancelDrag(); - m_document = 0; + mouseMovedIntoDocument(0); } + DragOperation DragController::dragUpdated(DragData* dragData) { @@ -175,7 +173,7 @@ DragOperation DragController::dragUpdated(DragData* dragData) bool DragController::performDrag(DragData* dragData) { ASSERT(dragData); - m_document = m_page->mainFrame()->documentAtPoint(dragData->clientPosition()); + m_documentUnderMouse = m_page->mainFrame()->documentAtPoint(dragData->clientPosition()); if (m_isHandlingDrag) { ASSERT(m_dragDestinationAction & DragDestinationActionDHTML); m_client->willPerformDragDestinationAction(DragDestinationActionDHTML, dragData); @@ -187,45 +185,48 @@ bool DragController::performDrag(DragData* dragData) mainFrame->eventHandler()->performDragAndDrop(createMouseEvent(dragData), clipboard.get()); clipboard->setAccessPolicy(ClipboardNumb); // invalidate clipboard here for security } - m_document = 0; + m_documentUnderMouse = 0; return true; } - if ((m_dragDestinationAction & DragDestinationActionEdit) && concludeDrag(dragData, m_dragDestinationAction)) { - m_document = 0; + if ((m_dragDestinationAction & DragDestinationActionEdit) && concludeEditDrag(dragData)) { + m_documentUnderMouse = 0; return true; } - m_document = 0; + m_documentUnderMouse = 0; if (operationForLoad(dragData) == DragOperationNone) return false; m_client->willPerformDragDestinationAction(DragDestinationActionLoad, dragData); - m_page->mainFrame()->loader()->load(ResourceRequest(dragData->asURL())); + m_page->mainFrame()->loader()->load(ResourceRequest(dragData->asURL()), false); return true; } - + +void DragController::mouseMovedIntoDocument(Document* newDocument) +{ + if (m_documentUnderMouse == newDocument) + return; + + // If we were over another document clear the selection + if (m_documentUnderMouse) + cancelDrag(); + m_documentUnderMouse = newDocument; +} + DragOperation DragController::dragEnteredOrUpdated(DragData* dragData) { ASSERT(dragData); - IntPoint windowPoint = dragData->clientPosition(); - - Document* newDraggingDoc = 0; - if (Frame* frame = m_page->mainFrame()) - newDraggingDoc = frame->documentAtPoint(windowPoint); - if (m_document != newDraggingDoc) { - if (m_document) - cancelDrag(); - m_document = newDraggingDoc; - } - + ASSERT(m_page->mainFrame()); // It is not possible in Mac WebKit to have a Page without a mainFrame() + mouseMovedIntoDocument(m_page->mainFrame()->documentAtPoint(dragData->clientPosition())); + m_dragDestinationAction = m_client->actionMaskForDrag(dragData); DragOperation operation = DragOperationNone; if (m_dragDestinationAction == DragDestinationActionNone) - cancelDrag(); + cancelDrag(); // FIXME: Why not call mouseMovedIntoDocument(0)? else { operation = tryDocumentDrag(dragData, m_dragDestinationAction); if (operation == DragOperationNone && (m_dragDestinationAction & DragDestinationActionLoad)) @@ -259,7 +260,7 @@ DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinatio { ASSERT(dragData); - if (!m_document) + if (!m_documentUnderMouse) return DragOperationNone; DragOperation operation = DragOperationNone; @@ -267,7 +268,7 @@ DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinatio operation = tryDHTMLDrag(dragData); m_isHandlingDrag = operation != DragOperationNone; - RefPtr<FrameView> frameView = m_document->view(); + RefPtr<FrameView> frameView = m_documentUnderMouse->view(); if (!frameView) return operation; @@ -277,18 +278,15 @@ DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinatio IntPoint dragPos = dragData->clientPosition(); IntPoint point = frameView->windowToContents(dragPos); - Element* element = m_document->elementFromPoint(point.x(), point.y()); + Element* element = m_documentUnderMouse->elementFromPoint(point.x(), point.y()); ASSERT(element); - Frame* innerFrame = element->document()->frame(); - ASSERT(innerFrame); if (!asFileInput(element)) { - Selection dragCaret; - if (Frame* frame = m_document->frame()) - dragCaret = frame->visiblePositionForPoint(point); + VisibleSelection dragCaret = m_documentUnderMouse->frame()->visiblePositionForPoint(point); m_page->dragCaretController()->setSelection(dragCaret); } - - return dragIsMove(innerFrame->selection(), dragData) ? DragOperationMove : DragOperationCopy; + + Frame* innerFrame = element->document()->frame(); + return dragIsMove(innerFrame->selection()) ? DragOperationMove : DragOperationCopy; } m_page->dragCaretController()->clear(); @@ -304,35 +302,33 @@ DragSourceAction DragController::delegateDragSourceAction(const IntPoint& window DragOperation DragController::operationForLoad(DragData* dragData) { ASSERT(dragData); - Document* doc = 0; - doc = m_page->mainFrame()->documentAtPoint(dragData->clientPosition()); + Document* doc = m_page->mainFrame()->documentAtPoint(dragData->clientPosition()); if (doc && (m_didInitiateDrag || doc->isPluginDocument() || (doc->frame() && doc->frame()->editor()->clientIsEditable()))) return DragOperationNone; 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(); } -bool DragController::concludeDrag(DragData* dragData, DragDestinationAction actionMask) +bool DragController::concludeEditDrag(DragData* dragData) { ASSERT(dragData); ASSERT(!m_isHandlingDrag); - ASSERT(actionMask & DragDestinationActionEdit); - if (!m_document) + if (!m_documentUnderMouse) return false; - IntPoint point = m_document->view()->windowToContents(dragData->clientPosition()); - Element* element = m_document->elementFromPoint(point.x(), point.y()); + IntPoint point = m_documentUnderMouse->view()->windowToContents(dragData->clientPosition()); + Element* element = m_documentUnderMouse->elementFromPoint(point.x(), point.y()); ASSERT(element); Frame* innerFrame = element->ownerDocument()->frame(); ASSERT(innerFrame); @@ -343,8 +339,8 @@ bool DragController::concludeDrag(DragData* dragData, DragDestinationAction acti return false; if (!innerFrame) return false; - RefPtr<Range> innerRange = innerFrame->selection()->toRange(); - RefPtr<CSSStyleDeclaration> style = m_document->createCSSStyleDeclaration(); + RefPtr<Range> innerRange = innerFrame->selection()->toNormalizedRange(); + RefPtr<CSSStyleDeclaration> style = m_documentUnderMouse->createCSSStyleDeclaration(); ExceptionCode ec; style->setProperty("color", color.name(), ec); if (!innerFrame->editor()->shouldApplyStyle(style.get(), innerRange.get())) @@ -360,8 +356,7 @@ bool DragController::concludeDrag(DragData* dragData, DragDestinationAction acti } if (HTMLInputElement* fileInput = asFileInput(element)) { - - if (!fileInput->isEnabled()) + if (!fileInput->isEnabledFormControl()) return false; if (!dragData->containsFiles()) @@ -384,9 +379,9 @@ bool DragController::concludeDrag(DragData* dragData, DragDestinationAction acti 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 @@ -394,7 +389,7 @@ bool DragController::concludeDrag(DragData* dragData, DragDestinationAction acti return false; DocLoader* loader = range->ownerDocument()->docLoader(); loader->setAllowStaleResources(true); - if (dragIsMove(innerFrame->selection(), dragData) || dragCaret.isContentRichlyEditable()) { + if (dragIsMove(innerFrame->selection()) || dragCaret.isContentRichlyEditable()) { bool chosePlainText = false; RefPtr<DocumentFragment> fragment = documentFragmentFromDragData(dragData, range, true, chosePlainText); if (!fragment || !innerFrame->editor()->shouldInsertFragment(fragment, range, EditorInsertActionDropped)) { @@ -403,14 +398,14 @@ bool DragController::concludeDrag(DragData* dragData, DragDestinationAction acti } m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); - if (dragIsMove(innerFrame->selection(), dragData)) { + if (dragIsMove(innerFrame->selection())) { bool smartMove = innerFrame->selectionGranularity() == WordGranularity && innerFrame->editor()->smartInsertDeleteEnabled() && dragData->canSmartReplace(); applyCommand(MoveSelectionCommand::create(fragment, dragCaret.base(), smartMove)); } else { if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) - applyCommand(ReplaceSelectionCommand::create(m_document, fragment, true, dragData->canSmartReplace(), chosePlainText)); + applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, fragment, true, dragData->canSmartReplace(), chosePlainText)); } } else { String text = dragData->asPlainText(); @@ -421,7 +416,7 @@ bool DragController::concludeDrag(DragData* dragData, DragDestinationAction acti m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) - applyCommand(ReplaceSelectionCommand::create(m_document, createFragmentFromText(range.get(), text), true, false, true)); + applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, createFragmentFromText(range.get(), text), true, false, true)); } loader->setAllowStaleResources(false); @@ -452,7 +447,7 @@ bool DragController::canProcessDrag(DragData* dragData) if (!result.innerNonSharedNode()->isContentEditable()) return false; - if (m_didInitiateDrag && m_document == m_dragInitiator && result.isSelected()) + if (m_didInitiateDrag && m_documentUnderMouse == m_dragInitiator && result.isSelected()) return false; return true; @@ -461,20 +456,20 @@ bool DragController::canProcessDrag(DragData* dragData) DragOperation DragController::tryDHTMLDrag(DragData* dragData) { ASSERT(dragData); - ASSERT(m_document); + ASSERT(m_documentUnderMouse); DragOperation op = DragOperationNone; - RefPtr<Frame> frame = m_page->mainFrame(); - RefPtr<FrameView> viewProtector = frame->view(); + RefPtr<Frame> mainFrame = m_page->mainFrame(); + RefPtr<FrameView> viewProtector = mainFrame->view(); if (!viewProtector) return DragOperationNone; - ClipboardAccessPolicy policy = frame->loader()->baseURL().isLocalFile() ? ClipboardReadable : ClipboardTypesReadable; + ClipboardAccessPolicy policy = m_documentUnderMouse->securityOrigin()->isLocal() ? ClipboardReadable : ClipboardTypesReadable; RefPtr<Clipboard> clipboard = dragData->createClipboard(policy); DragOperation srcOp = dragData->draggingSourceOperationMask(); clipboard->setSourceOperation(srcOp); PlatformMouseEvent event = createMouseEvent(dragData); - if (frame->eventHandler()->updateDragAndDrop(event, clipboard.get())) { + if (mainFrame->eventHandler()->updateDragAndDrop(event, clipboard.get())) { // *op unchanged if no source op was set if (!clipboard->destinationOperation(op)) { // The element accepted but they didn't pick an operation, so we pick one for them @@ -534,7 +529,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(); } @@ -545,7 +540,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; @@ -557,7 +552,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); } @@ -609,7 +604,7 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s IntPoint mouseDraggedPoint = src->view()->windowToContents(dragEvent.pos()); m_draggingImageURL = KURL(); - m_dragOperation = srcOp; + m_sourceDragOperation = srcOp; DragImageRef dragImage = 0; IntPoint dragLoc(0, 0); @@ -664,7 +659,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); @@ -676,7 +671,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); @@ -701,7 +696,7 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s deleteDragImage(dragImage); return startedDrag; } - + void DragController::doImageDrag(Element* element, const IntPoint& dragOrigin, const IntRect& rect, Clipboard* clipboard, Frame* frame, IntPoint& dragImageOffset) { IntPoint mouseDownPoint = dragOrigin; @@ -759,23 +754,16 @@ void DragController::doSystemDrag(DragImageRef image, const IntPoint& dragLoc, c // Manual drag caret manipulation void DragController::placeDragCaret(const IntPoint& windowPoint) { - Frame* mainFrame = m_page->mainFrame(); - Document* newDraggingDoc = mainFrame->documentAtPoint(windowPoint); - if (m_document != newDraggingDoc) { - if (m_document) - cancelDrag(); - m_document = newDraggingDoc; - } - if (!m_document) + mouseMovedIntoDocument(m_page->mainFrame()->documentAtPoint(windowPoint)); + if (!m_documentUnderMouse) return; - Frame* frame = m_document->frame(); - ASSERT(frame); + Frame* frame = m_documentUnderMouse->frame(); FrameView* frameView = frame->view(); if (!frameView) return; IntPoint framePoint = frameView->windowToContents(windowPoint); - Selection dragCaret(frame->visiblePositionForPoint(framePoint)); + VisibleSelection dragCaret(frame->visiblePositionForPoint(framePoint)); m_page->dragCaretController()->setSelection(dragCaret); } -} +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/DragController.h b/src/3rdparty/webkit/WebCore/page/DragController.h index 0c2504e..6fe1f7f 100644 --- a/src/3rdparty/webkit/WebCore/page/DragController.h +++ b/src/3rdparty/webkit/WebCore/page/DragController.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 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 @@ -29,7 +29,6 @@ #include "DragActions.h" #include "DragImage.h" #include "IntPoint.h" -#include "IntRect.h" #include "KURL.h" namespace WebCore { @@ -41,6 +40,7 @@ namespace WebCore { class Element; class Frame; class Image; + class IntRect; class Node; class Page; class PlatformMouseEvent; @@ -58,14 +58,13 @@ namespace WebCore { DragOperation dragUpdated(DragData*); bool performDrag(DragData*); - //FIXME: It should be possible to remove a number of these accessors once all - //drag logic is in WebCore + // FIXME: It should be possible to remove a number of these accessors once all + // drag logic is in WebCore. void setDidInitiateDrag(bool initiated) { m_didInitiateDrag = initiated; } bool didInitiateDrag() const { return m_didInitiateDrag; } void setIsHandlingDrag(bool handling) { m_isHandlingDrag = handling; } bool isHandlingDrag() const { return m_isHandlingDrag; } - void setDragOperation(DragOperation dragOp) { m_dragOperation = dragOp; } - DragOperation dragOperation() const { return m_dragOperation; } + DragOperation sourceDragOperation() const { return m_sourceDragOperation; } void setDraggingImageURL(const KURL& url) { m_draggingImageURL = url; } const KURL& draggingImageURL() const { return m_draggingImageURL; } void setDragInitiator(Document* initiator) { m_dragInitiator = initiator; m_didInitiateDrag = true; } @@ -73,8 +72,8 @@ namespace WebCore { void setDragOffset(const IntPoint& offset) { m_dragOffset = offset; } const IntPoint& dragOffset() const { return m_dragOffset; } DragSourceAction dragSourceAction() const { return m_dragSourceAction; } - - Document* document() const { return m_document; } + + Document* documentUnderMouse() const { return m_documentUnderMouse; } DragDestinationAction dragDestinationAction() const { return m_dragDestinationAction; } DragSourceAction delegateDragSourceAction(const IntPoint& pagePoint); @@ -91,40 +90,40 @@ namespace WebCore { static const int DragIconRightInset; static const int DragIconBottomInset; static const float DragImageAlpha; + private: bool canProcessDrag(DragData*); - bool concludeDrag(DragData*, DragDestinationAction); + bool concludeEditDrag(DragData*); DragOperation dragEnteredOrUpdated(DragData*); DragOperation operationForLoad(DragData*); DragOperation tryDocumentDrag(DragData*, DragDestinationAction); DragOperation tryDHTMLDrag(DragData*); DragOperation dragOperation(DragData*); void cancelDrag(); - bool dragIsMove(SelectionController*, DragData*); + bool dragIsMove(SelectionController*); bool isCopyKeyDown(); + void mouseMovedIntoDocument(Document*); + IntRect selectionDraggingRect(Frame*); bool doDrag(Frame* src, Clipboard* clipboard, DragImageRef dragImage, const KURL& linkURL, const KURL& imageURL, Node* node, IntPoint& dragLoc, IntPoint& dragImageOffset); void doImageDrag(Element*, const IntPoint&, const IntRect&, Clipboard*, Frame*, IntPoint&); void doSystemDrag(DragImageRef, const IntPoint&, const IntPoint&, Clipboard*, Frame*, bool forLink); void cleanupAfterSystemDrag(); + Page* m_page; DragClient* m_client; - //The Document the mouse was last dragged over - Document* m_document; - - //The Document (if any) that initiated the drag - Document* m_dragInitiator; + Document* m_documentUnderMouse; // The document the mouse was last dragged over. + Document* m_dragInitiator; // The Document (if any) that initiated the drag. DragDestinationAction m_dragDestinationAction; DragSourceAction m_dragSourceAction; bool m_didInitiateDrag; bool m_isHandlingDrag; - DragOperation m_dragOperation; + DragOperation m_sourceDragOperation; // Set in startDrag when a drag starts from a mouse down within WebKit IntPoint m_dragOffset; KURL m_draggingImageURL; - }; } diff --git a/src/3rdparty/webkit/WebCore/page/EditorClient.h b/src/3rdparty/webkit/WebCore/page/EditorClient.h index 56d0435..cdf0bd8 100644 --- a/src/3rdparty/webkit/WebCore/page/EditorClient.h +++ b/src/3rdparty/webkit/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,24 @@ struct GrammarDetail { String userDescription; }; +enum TextCheckingType { + TextCheckingTypeSpelling = 1 << 1, + TextCheckingTypeGrammar = 1 << 2, + TextCheckingTypeLink = 1 << 5, + TextCheckingTypeQuote = 1 << 6, + TextCheckingTypeDash = 1 << 7, + TextCheckingTypeReplacement = 1 << 8, + TextCheckingTypeCorrection = 1 << 9 +}; + +struct TextCheckingResult { + TextCheckingType type; + int location; + int length; + Vector<GrammarDetail> details; + String replacement; +}; + class EditorClient { public: virtual ~EditorClient() { } @@ -126,10 +144,33 @@ public: #endif #endif +#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + virtual void uppercaseWord() = 0; + virtual void lowercaseWord() = 0; + virtual void capitalizeWord() = 0; + virtual void showSubstitutionsPanel(bool show) = 0; + virtual bool substitutionsPanelIsShowing() = 0; + virtual void toggleSmartInsertDelete() = 0; + virtual bool isAutomaticQuoteSubstitutionEnabled() = 0; + virtual void toggleAutomaticQuoteSubstitution() = 0; + virtual bool isAutomaticLinkDetectionEnabled() = 0; + virtual void toggleAutomaticLinkDetection() = 0; + virtual bool isAutomaticDashSubstitutionEnabled() = 0; + virtual void toggleAutomaticDashSubstitution() = 0; + virtual bool isAutomaticTextReplacementEnabled() = 0; + virtual void toggleAutomaticTextReplacement() = 0; + virtual bool isAutomaticSpellingCorrectionEnabled() = 0; + virtual void toggleAutomaticSpellingCorrection() = 0; +#endif + virtual void ignoreWordInSpellDocument(const String&) = 0; virtual void learnWord(const String&) = 0; virtual void checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength) = 0; + virtual String getAutoCorrectSuggestionForMisspelledWord(const String& misspelledWord) = 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 checkTextOfParagraph(const UChar* text, int length, uint64_t checkingTypes, 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; @@ -141,3 +182,4 @@ public: } #endif // EditorClient_h + diff --git a/src/3rdparty/webkit/WebCore/page/EventHandler.cpp b/src/3rdparty/webkit/WebCore/page/EventHandler.cpp index cc0e358..f020e7a 100644 --- a/src/3rdparty/webkit/WebCore/page/EventHandler.cpp +++ b/src/3rdparty/webkit/WebCore/page/EventHandler.cpp @@ -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. * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) * * Redistribution and use in source and binary forms, with or without @@ -42,12 +42,12 @@ #include "FrameLoader.h" #include "FrameTree.h" #include "FrameView.h" -#include "HitTestRequest.h" -#include "HitTestResult.h" -#include "HTMLFrameSetElement.h" #include "HTMLFrameElementBase.h" +#include "HTMLFrameSetElement.h" #include "HTMLInputElement.h" #include "HTMLNames.h" +#include "HitTestRequest.h" +#include "HitTestResult.h" #include "Image.h" #include "InspectorController.h" #include "KeyboardEvent.h" @@ -57,12 +57,14 @@ #include "PlatformKeyboardEvent.h" #include "PlatformWheelEvent.h" #include "RenderFrameSet.h" -#include "RenderWidget.h" +#include "RenderTextControlSingleLine.h" #include "RenderView.h" +#include "RenderWidget.h" #include "Scrollbar.h" #include "SelectionController.h" #include "Settings.h" #include "TextEvent.h" +#include "htmlediting.h" // for comparePositions() #include <wtf/StdLibExtras.h> #if ENABLE(SVG) @@ -102,21 +104,38 @@ static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDir { if (!delta) return; + + // Find the nearest enclosing box. + RenderBox* enclosingBox = node->renderer()->enclosingBox(); + if (e.granularity() == ScrollByPageWheelEvent) { - if (node->renderer()->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, 1)) + if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, 1)) e.accept(); return; } float pixelsToScroll = delta > 0 ? delta : -delta; - if (e.granularity() == ScrollByLineWheelEvent) - pixelsToScroll *= cMouseWheelPixelsPerLineStep; - if (node->renderer()->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll)) + if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll)) e.accept(); } +#if !PLATFORM(MAC) + +inline bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&) +{ + return false; +} + +inline bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&) +{ + return false; +} + +#endif + EventHandler::EventHandler(Frame* frame) : m_frame(frame) , m_mousePressed(false) + , m_capturesDragging(false) , m_mouseDownMayStartSelect(false) , m_mouseDownMayStartDrag(false) , m_mouseDownWasSingleClickInSelection(false) @@ -135,8 +154,6 @@ EventHandler::EventHandler(Frame* frame) , m_capturingMouseEventsNode(0) , m_clickCount(0) , m_mouseDownTimestamp(0) - , m_pendingFrameUnloadEventCount(0) - , m_pendingFrameBeforeUnloadEventCount(0) #if PLATFORM(MAC) , m_mouseDownView(nil) , m_sendingEventToSubview(false) @@ -174,18 +191,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); } @@ -209,11 +227,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); @@ -252,10 +270,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()) { @@ -271,9 +289,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; @@ -283,10 +298,12 @@ bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR // Don't restart the selection when the mouse is pressed on an // existing selection so we can allow for text dragging. - IntPoint vPoint = m_frame->view()->windowToContents(event.event().pos()); - if (!extendSelection && m_frame->selection()->contains(vPoint)) { - m_mouseDownWasSingleClickInSelection = true; - return false; + if (FrameView* view = m_frame->view()) { + IntPoint vPoint = view->windowToContents(event.event().pos()); + if (!extendSelection && m_frame->selection()->contains(vPoint)) { + m_mouseDownWasSingleClickInSelection = true; + return false; + } } VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint())); @@ -294,7 +311,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); @@ -302,17 +319,16 @@ 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()); - if (before <= 0) - newSelection = Selection(pos, end); + if (comparePositions(pos, start) <= 0) + 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); } @@ -363,21 +379,19 @@ 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->renderer() && m_mousePressNode->renderer()->canBeProgramaticallyScrolled(true)); + m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect || + (m_mousePressNode && m_mousePressNode->renderBox() && m_mousePressNode->renderBox()->canBeProgramaticallyScrolled(true)); return swallowEvent; } @@ -404,7 +418,7 @@ bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e // If the selection is contained in a layer that can scroll, that layer should handle the autoscroll // Otherwise, let the bridge handle it so the view can scroll itself. RenderObject* renderer = targetNode->renderer(); - while (renderer && !renderer->canBeProgramaticallyScrolled(false)) { + while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeProgramaticallyScrolled(false))) { if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement()) renderer = renderer->document()->ownerElement()->renderer(); else @@ -429,8 +443,10 @@ bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const // that its logic needs to stay in sync with handleMouseMoveEvent() and the way we setMouseDownMayStartDrag // in handleMousePressEvent - if (!m_frame->contentRenderer() || !m_frame->contentRenderer()->hasLayer() - || event.button() != LeftButton || event.clickCount() != 1) + if (!m_frame->contentRenderer() || !m_frame->contentRenderer()->hasLayer()) + return false; + + if (event.button() != LeftButton || event.clickCount() != 1) return false; bool DHTMLFlag; @@ -438,9 +454,13 @@ bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const allowDHTMLDrag(DHTMLFlag, UAFlag); if (!DHTMLFlag && !UAFlag) return false; - - HitTestRequest request(true, false); - HitTestResult result(m_frame->view()->windowToContents(event.pos())); + + FrameView* view = m_frame->view(); + if (!view) + return false; + + HitTestRequest request(HitTestRequest::ReadOnly); + HitTestResult result(view->windowToContents(event.pos())); m_frame->contentRenderer()->layer()->hitTest(request, result); bool srcIsDHTML; return result.innerNode() && result.innerNode()->renderer()->draggableNode(DHTMLFlag, UAFlag, result.point().x(), result.point().y(), srcIsDHTML); @@ -451,15 +471,18 @@ void EventHandler::updateSelectionForMouseDrag() FrameView* view = m_frame->view(); if (!view) return; - RenderObject* renderer = m_frame->contentRenderer(); + RenderView* renderer = m_frame->contentRenderer(); if (!renderer) return; RenderLayer* layer = renderer->layer(); 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()); } @@ -486,7 +509,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. @@ -500,7 +523,7 @@ void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint& if (!m_beganSelectingText) { m_beganSelectingText = true; - newSelection = Selection(targetPosition); + newSelection = VisibleSelection(targetPosition); } newSelection.setExtent(targetPosition); @@ -538,6 +561,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; @@ -545,17 +569,20 @@ bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e bool handled = false; - // Clear the selection if the mouse didn't move after the last mouse press. - // We do this so when clicking on the selection, the selection goes away. - // However, if we are editing, place the caret. + // Clear the selection if the mouse didn't move after the last mouse + // press and it's not a context menu click. We do this so when clicking + // on the selection, the selection goes away. However, if we are + // editing, place the caret. if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText && m_dragStartPos == event.event().pos() - && m_frame->selection()->isRange()) { - Selection newSelection; + && m_frame->selection()->isRange() + && event.event().button() != RightButton) { + VisibleSelection newSelection; Node *node = event.targetNode(); - if (node && node->isContentEditable() && node->renderer()) { + bool caretBrowsing = m_frame->settings()->caretBrowsingEnabled(); + if (node && (caretBrowsing || 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); @@ -581,10 +608,14 @@ void EventHandler::handleAutoscroll(RenderObject* renderer) #if ENABLE(PAN_SCROLLING) if (m_panScrollInProgress) { m_panScrollStartPos = currentMousePosition(); - m_frame->view()->addPanScrollIcon(m_panScrollStartPos); - // If we're not in the top frame we notify it that we are using the panScroll - if (m_frame != m_frame->page()->mainFrame()) - m_frame->page()->mainFrame()->eventHandler()->setPanScrollInProgress(true); + if (FrameView* view = m_frame->view()) + view->addPanScrollIcon(m_panScrollStartPos); + // If we're not in the top frame we notify it that we doing a panScroll. + if (Page* page = m_frame->page()) { + Frame* mainFrame = page->mainFrame(); + if (m_frame != mainFrame) + mainFrame->eventHandler()->setPanScrollInProgress(true); + } } #endif @@ -594,7 +625,7 @@ void EventHandler::handleAutoscroll(RenderObject* renderer) void EventHandler::autoscrollTimerFired(Timer<EventHandler>*) { RenderObject* r = autoscrollRenderer(); - if (!r) { + if (!r || !r->isBox()) { stopAutoscrollTimer(); return; } @@ -604,22 +635,30 @@ void EventHandler::autoscrollTimerFired(Timer<EventHandler>*) stopAutoscrollTimer(); return; } - r->autoscroll(); + toRenderBox(r)->autoscroll(); } else { // we verify that the main frame hasn't received the order to stop the panScroll - if (!m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress()) { - stopAutoscrollTimer(); - return; + if (Page* page = m_frame->page()) { + if (!page->mainFrame()->eventHandler()->panScrollInProgress()) { + stopAutoscrollTimer(); + return; + } } #if ENABLE(PAN_SCROLLING) setPanScrollCursor(); - r->panScroll(m_panScrollStartPos); + toRenderBox(r)->panScroll(m_panScrollStartPos); #endif } } +#if ENABLE(PAN_SCROLLING) + void EventHandler::setPanScrollCursor() { + FrameView* view = m_frame->view(); + if (!view) + return; + // At the original click location we draw a 4 arrowed icon. Over this icon there won't be any scroll // So we don't want to change the cursor over this area const int noScrollRadius = 9; @@ -630,26 +669,28 @@ void EventHandler::setPanScrollCursor() if (north) { if (east) - m_frame->view()->setCursor(northEastPanningCursor()); + view->setCursor(northEastPanningCursor()); else if (west) - m_frame->view()->setCursor(northWestPanningCursor()); + view->setCursor(northWestPanningCursor()); else - m_frame->view()->setCursor(northPanningCursor()); + view->setCursor(northPanningCursor()); } else if (south) { if (east) - m_frame->view()->setCursor(southEastPanningCursor()); + view->setCursor(southEastPanningCursor()); else if (west) - m_frame->view()->setCursor(southWestPanningCursor()); + view->setCursor(southWestPanningCursor()); else - m_frame->view()->setCursor(southPanningCursor()); + view->setCursor(southPanningCursor()); } else if (east) - m_frame->view()->setCursor(eastPanningCursor()); + view->setCursor(eastPanningCursor()); else if (west) - m_frame->view()->setCursor(westPanningCursor()); + view->setCursor(westPanningCursor()); else - m_frame->view()->setCursor(middlePanningCursor()); + view->setCursor(middlePanningCursor()); } +#endif // ENABLE(PAN_SCROLLING) + RenderObject* EventHandler::autoscrollRenderer() const { return m_autoscrollRenderer; @@ -665,7 +706,7 @@ void EventHandler::updateAutoscrollRenderer() if (Node* nodeAtPoint = hitTest.innerNode()) m_autoscrollRenderer = nodeAtPoint->renderer(); - while (m_autoscrollRenderer && !m_autoscrollRenderer->canBeProgramaticallyScrolled(false)) + while (m_autoscrollRenderer && (!m_autoscrollRenderer->isBox() || !toRenderBox(m_autoscrollRenderer)->canBeProgramaticallyScrolled(false))) m_autoscrollRenderer = m_autoscrollRenderer->parent(); } @@ -676,50 +717,68 @@ void EventHandler::setAutoscrollRenderer(RenderObject* renderer) void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const { - if (!m_frame || !m_frame->document()) { - flagDHTML = false; - flagUA = false; + flagDHTML = false; + flagUA = false; + + if (!m_frame) return; - } - - unsigned mask = m_frame->page()->dragController()->delegateDragSourceAction(m_frame->view()->contentsToWindow(m_mouseDownPos)); + + Page* page = m_frame->page(); + if (!page) + return; + + FrameView* view = m_frame->view(); + if (!view) + return; + + unsigned mask = page->dragController()->delegateDragSourceAction(view->contentsToWindow(m_mouseDownPos)); flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone; 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(); if (!result.isOverWidget() || !n || !n->renderer() || !n->renderer()->isWidget()) break; - Widget* widget = static_cast<RenderWidget*>(n->renderer())->widget(); + RenderWidget* renderWidget = static_cast<RenderWidget*>(n->renderer()); + Widget* widget = renderWidget->widget(); if (!widget || !widget->isFrameView()) break; Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame(); if (!frame || !frame->contentRenderer()) break; FrameView* view = static_cast<FrameView*>(widget); - IntPoint widgetPoint(result.localPoint().x() + view->scrollX() - n->renderer()->borderLeft() - n->renderer()->paddingLeft(), - result.localPoint().y() + view->scrollY() - n->renderer()->borderTop() - n->renderer()->paddingTop()); + 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; } // If our HitTestResult is not visible, then we started hit testing too far down the frame chain. // Another hit test at the main frame level should get us the correct visible result. Frame* resultFrame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : 0; - Frame* mainFrame = m_frame->page()->mainFrame(); - 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); + if (Page* page = m_frame->page()) { + Frame* mainFrame = page->mainFrame(); + if (m_frame != mainFrame && resultFrame && resultFrame != mainFrame && !resultFrame->editor()->insideVisibleArea(result.point())) { + FrameView* resultView = resultFrame->view(); + FrameView* mainView = mainFrame->view(); + if (resultView && mainView) { + IntPoint windowPoint = resultView->contentsToWindow(result.point()); + IntPoint mainFramePoint = mainView->windowToContents(windowPoint); + result = mainFrame->eventHandler()->hitTestResultAtPoint(mainFramePoint, allowShadowContent, ignoreClipping); + } + } } if (!allowShadowContent) @@ -746,11 +805,13 @@ void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed) if (autoscrollRenderer()) { if (!rendererIsBeingDestroyed && (m_autoscrollInProgress || m_panScrollInProgress)) - autoscrollRenderer()->stopAutoscroll(); + toRenderBox(autoscrollRenderer())->stopAutoscroll(); #if ENABLE(PAN_SCROLLING) if (m_panScrollInProgress) { - m_frame->view()->removePanScrollIcon(); - m_frame->view()->setCursor(pointerCursor()); + if (FrameView* view = m_frame->view()) { + view->removePanScrollIcon(); + view->setCursor(pointerCursor()); + } } #endif @@ -760,9 +821,14 @@ void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed) m_autoscrollTimer.stop(); m_panScrollInProgress = false; - // If we're not in the top frame we notify it that we are not using the panScroll anymore - if (m_frame->page() && m_frame != m_frame->page()->mainFrame()) - m_frame->page()->mainFrame()->eventHandler()->setPanScrollInProgress(false); + + // If we're not in the top frame we notify it that we are not doing a panScroll any more. + if (Page* page = m_frame->page()) { + Frame* mainFrame = page->mainFrame(); + if (m_frame != mainFrame) + mainFrame->eventHandler()->setPanScrollInProgress(false); + } + m_autoscrollInProgress = false; } @@ -778,17 +844,14 @@ 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(); if (node) { - RenderObject *r = node->renderer(); + RenderObject* r = node->renderer(); if (r && !r->isListBox()) - return r->scroll(direction, granularity); + return r->enclosingBox()->scroll(direction, granularity); } return false; @@ -905,10 +968,13 @@ Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scr if ((event.isOverLink() || isSubmitImage(node)) && (!editable || editableLinkEnabled)) return handCursor(); - RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0; bool inResizer = false; - if (m_frame->view() && layer && layer->isPointInResizeControl(m_frame->view()->windowToContents(event.event().pos()))) - inResizer = true; + if (renderer) { + if (RenderLayer* layer = renderer->enclosingLayer()) { + if (FrameView* view = m_frame->view()) + inResizer = layer->isPointInResizeControl(view->windowToContents(event.event().pos())); + } + } if ((editable || (renderer && renderer->isText() && node->canStartSelection())) && !inResizer && !scrollbar) return iBeamCursor(); return pointerCursor(); @@ -986,24 +1052,39 @@ Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Scr } return pointerCursor(); } + +static IntPoint documentPointForWindowPoint(Frame* frame, const IntPoint& windowPoint) +{ + FrameView* view = frame->view(); + // FIXME: Is it really OK to use the wrong coordinates here when view is 0? + // Historically the code would just crash; this is clearly no worse than that. + return view ? view->windowToContents(windowPoint) : windowPoint; +} 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; m_mouseDownMayStartSelect = false; m_mouseDownMayStartAutoscroll = false; - m_mouseDownPos = m_frame->view()->windowToContents(mouseEvent.pos()); + if (FrameView* view = m_frame->view()) + m_mouseDownPos = view->windowToContents(mouseEvent.pos()); + else { + invalidateClick(); + return false; + } m_mouseDownWasInSubframe = false; - MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, true), mouseEvent); + HitTestRequest request(HitTestRequest::Active); + // Save the document point we generate in case the window coordinate is invalidated by what happens + // when we dispatch the event. + IntPoint documentPoint = documentPointForWindowPoint(m_frame, mouseEvent.pos()); + MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent); if (!mev.targetNode()) { invalidateClick(); @@ -1012,34 +1093,38 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) m_mousePressNode = mev.targetNode(); - InspectorController* inspector = m_frame->page()->inspectorController(); - if (inspector && inspector->enabled() && inspector->searchingForNodeInPage()) { - inspector->handleMousePressOnNode(m_mousePressNode.get()); - invalidateClick(); - return true; + if (Page* page = m_frame->page()) { + InspectorController* inspector = page->inspectorController(); + if (inspector && inspector->enabled() && inspector->searchingForNodeInPage()) { + inspector->handleMousePressOnNode(m_mousePressNode.get()); + invalidateClick(); + return true; + } } Frame* subframe = subframeForHitTestResult(mev); 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; } #if ENABLE(PAN_SCROLLING) - if (m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) { + Page* page = m_frame->page(); + if (page && page->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) { stopAutoscrollTimer(); invalidateClick(); return true; } - + if (mouseEvent.button() == MiddleButton && !mev.isOverLink()) { RenderObject* renderer = mev.targetNode()->renderer(); - while (renderer && !renderer->canBeProgramaticallyScrolled(false)) { + while (renderer && (!renderer->isBox() || !toRenderBox(renderer)->canBeProgramaticallyScrolled(false))) { if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement()) renderer = renderer->document()->ownerElement()->renderer(); else @@ -1057,25 +1142,28 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) m_clickCount = mouseEvent.clickCount(); m_clickNode = mev.targetNode(); - - RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0; - IntPoint p = m_frame->view()->windowToContents(mouseEvent.pos()); - if (layer && layer->isPointInResizeControl(p)) { - layer->setInResizeMode(true); - m_resizeLayer = layer; - m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p); - invalidateClick(); - return true; + + if (FrameView* view = m_frame->view()) { + RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->enclosingLayer() : 0; + IntPoint p = view->windowToContents(mouseEvent.pos()); + if (layer && layer->isPointInResizeControl(p)) { + layer->setInResizeMode(true); + m_resizeLayer = layer; + m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p); + invalidateClick(); + return true; + } } 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 = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent); if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get()) m_lastScrollbarUnderMouse = 0; } @@ -1089,10 +1177,13 @@ 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 = m_frame->document()->prepareMouseEvent(request, documentPoint, mouseEvent); + } - Scrollbar* scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent); + FrameView* view = m_frame->view(); + Scrollbar* scrollbar = view ? view->scrollbarUnderMouse(mouseEvent) : 0; if (!scrollbar) scrollbar = mev.scrollbar(); if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar)) @@ -1107,16 +1198,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; @@ -1165,7 +1254,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()); @@ -1192,7 +1281,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(); @@ -1202,8 +1296,8 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi if (m_resizeLayer && m_resizeLayer->inResizeMode()) m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner); else { - if (m_frame->view()) - scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent); + if (FrameView* view = m_frame->view()) + scrollbar = view->scrollbarUnderMouse(mouseEvent); if (!scrollbar) scrollbar = mev.scrollbar(); @@ -1234,8 +1328,12 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi } else { if (scrollbar && !m_mousePressed) scrollbar->mouseMoved(scrollbar->transformEvent(mouseEvent)); // Handle hover effects on platforms that support visual feedback on scrollbar hovering. - if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() && m_frame->view()) - m_frame->view()->setCursor(selectCursor(mev, scrollbar)); + if (Page* page = m_frame->page()) { + if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !page->mainFrame()->eventHandler()->panScrollInProgress()) { + if (FrameView* view = m_frame->view()) + view->setCursor(selectCursor(mev, scrollbar)); + } + } } m_lastMouseMoveEventSubframe = newSubframe; @@ -1258,9 +1356,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; @@ -1282,7 +1377,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; @@ -1312,16 +1408,23 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard) { - IntPoint contentsPos = m_frame->view()->windowToContents(event.pos()); - + FrameView* view = m_frame->view(); + + // FIXME: We might want to dispatch a dragleave even if the view is gone. + if (!view) + return false; + + view->resetDeferredRepaintDelay(); + IntPoint contentsPos = view->windowToContents(event.pos()); + RefPtr<MouseEvent> me = MouseEvent::create(eventType, true, true, m_frame->document()->defaultView(), 0, event.globalX(), event.globalY(), contentsPos.x(), contentsPos.y(), event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), 0, 0, clipboard); - ExceptionCode ec = 0; - EventTargetNodeCast(dragTarget)->dispatchEvent(me.get(), ec); + ExceptionCode ec; + dragTarget->dispatchEvent(me.get(), ec); return me->defaultPrevented(); } @@ -1329,13 +1432,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(); @@ -1348,12 +1449,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; @@ -1363,11 +1465,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; @@ -1421,8 +1524,7 @@ MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestReques ASSERT(m_frame); ASSERT(m_frame->document()); - IntPoint documentPoint = m_frame->view()->windowToContents(mev.pos()); - return m_frame->document()->prepareMouseEvent(request, documentPoint, mev); + return m_frame->document()->prepareMouseEvent(request, documentPointForWindowPoint(m_frame, mev.pos()), mev); } #if ENABLE(SVG) @@ -1507,10 +1609,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) @@ -1521,12 +1623,15 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool /*cancelable*/, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder) { + if (FrameView* view = m_frame->view()) + 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 @@ -1538,7 +1643,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 @@ -1547,7 +1652,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; @@ -1556,14 +1661,17 @@ bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe renderer = renderer->parent(); } + // If focus shift is blocked, we eat the event. Note we should never clear swallowEvent // if the page already set it (e.g., by canceling default behavior). - if (node && node->isMouseFocusable()) { - if (!m_frame->page()->focusController()->setFocusedNode(node, m_frame)) - swallowEvent = true; - } else if (!node || !node->focused()) { - if (!m_frame->page()->focusController()->setFocusedNode(0, m_frame)) - swallowEvent = true; + if (Page* page = m_frame->page()) { + if (node && node->isMouseFocusable()) { + if (!page->focusController()->setFocusedNode(node, m_frame)) + swallowEvent = true; + } else if (!node || !node->focused()) { + if (!page->focusController()->setFocusedNode(0, m_frame)) + swallowEvent = true; + } } } @@ -1573,18 +1681,21 @@ 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) return false; + + RefPtr<FrameView> protector(m_frame->view()); - IntPoint vPoint = m_frame->view()->windowToContents(e.pos()); + FrameView* view = m_frame->view(); + if (!view) + return false; + IntPoint vPoint = view->windowToContents(e.pos()); - HitTestRequest request(true, false); + HitTestRequest request(HitTestRequest::ReadOnly); HitTestResult result(vPoint); - doc->renderer()->layer()->hitTest(request, result); + doc->renderView()->layer()->hitTest(request, result); Node* node = result.innerNode(); if (node) { @@ -1601,11 +1712,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); @@ -1613,9 +1729,14 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e) } } - if (!e.isAccepted()) - m_frame->view()->wheelEvent(e); - + if (e.isAccepted()) + return true; + + view = m_frame->view(); + if (!view) + return false; + + view->wheelEvent(e); return e.isAccepted(); } @@ -1623,20 +1744,23 @@ 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. -#if !PLATFORM(GTK) + // 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. + // See: https://bugs.webkit.org/show_bug.cgi?id=15279 +#if !PLATFORM(GTK) && !PLATFORM(CHROMIUM) if (!m_frame->selection()->contains(viewportPos) && // 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); } @@ -1663,10 +1787,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->dispatchEvent(eventNames().selectstartEvent, true, true); + } + return true; } @@ -1675,10 +1800,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->dispatchEvent(eventNames().selectstartEvent, true, true); + } + return true; } @@ -1700,27 +1826,26 @@ void EventHandler::hoverTimerFired(Timer<EventHandler>*) ASSERT(m_frame); ASSERT(m_frame->document()); - if (RenderObject* renderer = m_frame->contentRenderer()) { - HitTestResult result(m_frame->view()->windowToContents(m_currentMousePosition)); - renderer->layer()->hitTest(HitTestRequest(false, false, true), result); - m_frame->document()->updateRendering(); + if (RenderView* renderer = m_frame->contentRenderer()) { + if (FrameView* view = m_frame->view()) { + HitTestRequest request(HitTestRequest::MouseMove); + HitTestResult result(view->windowToContents(m_currentMousePosition)); + renderer->layer()->hitTest(request, result); + m_frame->document()->updateStyleIfNeeded(); + } } } -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) @@ -1750,23 +1875,29 @@ bool EventHandler::needsKeyboardEventDisambiguationQuirks() const bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) { #if ENABLE(PAN_SCROLLING) - if (m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) { - String escKeyId = "U+001B"; - // If a key is pressed while the autoscroll/panScroll is in progress then we want to stop - if (initialKeyEvent.keyIdentifier() == escKeyId && initialKeyEvent.type() == PlatformKeyboardEvent::KeyUp) - stopAutoscrollTimer(); + if (Page* page = m_frame->page()) { + if (page->mainFrame()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress) { + static const char* const escapeKeyIdentifier = "U+001B"; - // If we were in autoscroll/panscroll mode, we swallow the key event - return true; + // If a key is pressed while the autoscroll/panScroll is in progress then we want to stop + if (initialKeyEvent.keyIdentifier() == escapeKeyIdentifier && initialKeyEvent.type() == PlatformKeyboardEvent::KeyUp) + stopAutoscrollTimer(); + + // If we were in autoscroll/panscroll mode, we swallow the key event + return true; + } } #endif // 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; + if (FrameView* view = m_frame->view()) + view->resetDeferredRepaintDelay(); + // FIXME: what is this doing here, in keyboard event handler? m_frame->loader()->resetMultipleFormSubmissionProtection(); @@ -1852,21 +1983,22 @@ void EventHandler::handleKeyboardSelectionMovement(KeyboardEvent* event) String key = event->keyIdentifier(); bool isShifted = event->getModifierState("Shift"); bool isOptioned = event->getModifierState("Alt"); + bool isCommanded = event->getModifierState("Meta"); if (key == "Up") { - m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::BACKWARD, LineGranularity, true); + m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::BACKWARD, (isCommanded) ? DocumentBoundary : LineGranularity, true); event->setDefaultHandled(); } else if (key == "Down") { - m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::FORWARD, LineGranularity, true); + m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::FORWARD, (isCommanded) ? DocumentBoundary : LineGranularity, true); event->setDefaultHandled(); } else if (key == "Left") { - m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::LEFT, (isOptioned) ? WordGranularity : CharacterGranularity, true); + m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::LEFT, (isCommanded) ? LineBoundary : (isOptioned) ? WordGranularity : CharacterGranularity, true); event->setDefaultHandled(); } else if (key == "Right") { - m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::RIGHT, (isOptioned) ? WordGranularity : CharacterGranularity, true); + m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::RIGHT, (isCommanded) ? LineBoundary : (isOptioned) ? WordGranularity : CharacterGranularity, true); event->setDefaultHandled(); } } @@ -1877,11 +2009,8 @@ void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event) m_frame->editor()->handleKeyboardEvent(event); if (event->defaultHandled()) return; - const String& keyIdentifier = event->keyIdentifier(); - if (keyIdentifier == "U+0009") + if (event->keyIdentifier() == "U+0009") defaultTabEventHandler(event); - else if (keyIdentifier == "U+0020") - defaultSpaceEventHandler(event); // provides KB navigation and selection for enhanced accessibility users if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled()) @@ -1904,7 +2033,10 @@ bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLoc bool EventHandler::dragHysteresisExceeded(const IntPoint& dragViewportLocation) const { - IntPoint dragLocation = m_frame->view()->windowToContents(dragViewportLocation); + FrameView* view = m_frame->view(); + if (!view) + return false; + IntPoint dragLocation = view->windowToContents(dragViewportLocation); IntSize delta = dragLocation - m_mouseDownPos; int threshold = GeneralDragHysteresis; @@ -1926,10 +2058,10 @@ 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); + Page* page = m_frame->page(); + return page && page->dragController()->mayStartDragAtEventLocation(m_frame, point); } void EventHandler::dragSourceMovedTo(const PlatformMouseEvent& event) @@ -1980,7 +2112,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(); @@ -2018,7 +2150,8 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event) return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll; // We are starting a text/image/url drag, so the cursor should be an arrow - m_frame->view()->setCursor(pointerCursor()); + if (FrameView* view = m_frame->view()) + view->setCursor(pointerCursor()); if (!dragHysteresisExceeded(event.event().pos())) return true; @@ -2068,7 +2201,8 @@ bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event) } if (m_mouseDownMayStartDrag) { - DragController* dragController = m_frame->page() ? m_frame->page()->dragController() : 0; + Page* page = m_frame->page(); + DragController* dragController = page ? page->dragController() : 0; bool startedDrag = dragController && dragController->startDrag(m_frame, dragState().m_dragClipboard.get(), srcOp, event.event(), m_mouseDownPos, dragState().m_dragSrcIsDHTML); if (!startedDrag && dragState().m_dragSrcMayBeDHTML) { // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event @@ -2104,6 +2238,9 @@ bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEve target = eventTargetNodeForDocument(m_frame->document()); if (!target) return false; + + if (FrameView* view = m_frame->view()) + view->resetDeferredRepaintDelay(); RefPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text); event->setUnderlyingEvent(underlyingEvent); @@ -2205,64 +2342,27 @@ 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(); -} - -unsigned EventHandler::pendingFrameUnloadEventCount() -{ - return m_pendingFrameUnloadEventCount; -} - -void EventHandler::addPendingFrameUnloadEventCount() -{ - m_pendingFrameUnloadEventCount += 1; - m_frame->page()->changePendingUnloadEventCount(1); - return; -} - -void EventHandler::removePendingFrameUnloadEventCount() -{ - ASSERT( (-1 + (int)m_pendingFrameUnloadEventCount) >= 0 ); - m_pendingFrameUnloadEventCount -= 1; - m_frame->page()->changePendingUnloadEventCount(-1); - return; -} - -void EventHandler::clearPendingFrameUnloadEventCount() -{ - m_frame->page()->changePendingUnloadEventCount(-((int)m_pendingFrameUnloadEventCount)); - m_pendingFrameUnloadEventCount = 0; - return; + 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::pendingFrameBeforeUnloadEventCount() +void EventHandler::sendResizeEvent() { - return m_pendingFrameBeforeUnloadEventCount; + m_frame->document()->dispatchWindowEvent(eventNames().resizeEvent, false, false); } -void EventHandler::addPendingFrameBeforeUnloadEventCount() -{ - m_pendingFrameBeforeUnloadEventCount += 1; - m_frame->page()->changePendingBeforeUnloadEventCount(1); - return; -} - -void EventHandler::removePendingFrameBeforeUnloadEventCount() +void EventHandler::sendScrollEvent() { - ASSERT( (-1 + (int)m_pendingFrameBeforeUnloadEventCount) >= 0 ); - m_pendingFrameBeforeUnloadEventCount -= 1; - m_frame->page()->changePendingBeforeUnloadEventCount(-1); - return; -} - - void EventHandler::clearPendingFrameBeforeUnloadEventCount() -{ - m_frame->page()->changePendingBeforeUnloadEventCount(-((int)m_pendingFrameBeforeUnloadEventCount)); - m_pendingFrameBeforeUnloadEventCount = 0; - return; + FrameView* v = m_frame->view(); + if (!v) + return; + v->setWasScrolledByUser(true); + m_frame->document()->dispatchEvent(eventNames().scrollEvent, true, false); } bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, Scrollbar* scrollbar) diff --git a/src/3rdparty/webkit/WebCore/page/EventHandler.h b/src/3rdparty/webkit/WebCore/page/EventHandler.h index 5d51cb6..06ed956 100644 --- a/src/3rdparty/webkit/WebCore/page/EventHandler.h +++ b/src/3rdparty/webkit/WebCore/page/EventHandler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 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 @@ -27,33 +27,25 @@ #define EventHandler_h #include "DragActions.h" -#include "FocusDirection.h" #include "PlatformMouseEvent.h" #include "ScrollTypes.h" #include "Timer.h" #include <wtf/Forward.h> -#include <wtf/Noncopyable.h> -#include <wtf/Platform.h> #include <wtf/RefPtr.h> -#if PLATFORM(MAC) -#include "WebCoreKeyboardUIMode.h" -#ifndef __OBJC__ -class NSEvent; +#if PLATFORM(MAC) && !defined(__OBJC__) class NSView; #endif -#endif 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; @@ -68,11 +60,8 @@ class Scrollbar; class String; class SVGElementInstance; class TextEvent; -class VisiblePosition; class Widget; -struct HitTestRequest; - extern const int LinkDragHysteresis; extern const int ImageDragHysteresis; extern const int TextDragHysteresis; @@ -97,7 +86,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; } @@ -158,30 +147,27 @@ public: void capsLockStateMayHaveChanged(); - unsigned pendingFrameUnloadEventCount(); - void addPendingFrameUnloadEventCount(); - void removePendingFrameUnloadEventCount(); - void clearPendingFrameUnloadEventCount(); - unsigned pendingFrameBeforeUnloadEventCount(); - void addPendingFrameBeforeUnloadEventCount(); - void removePendingFrameBeforeUnloadEventCount(); - void clearPendingFrameBeforeUnloadEventCount(); + void sendResizeEvent(); + void sendScrollEvent(); -#if PLATFORM(MAC) +#if PLATFORM(MAC) && defined(__OBJC__) PassRefPtr<KeyboardEvent> currentKeyboardEvent() const; - void mouseDown(NSEvent*); - void mouseDragged(NSEvent*); - void mouseUp(NSEvent*); - void mouseMoved(NSEvent*); - bool keyEvent(NSEvent*); - bool wheelEvent(NSEvent*); + void mouseDown(NSEvent *); + void mouseDragged(NSEvent *); + void mouseUp(NSEvent *); + void mouseMoved(NSEvent *); + bool keyEvent(NSEvent *); + bool wheelEvent(NSEvent *); + + bool sendContextMenuEvent(NSEvent *); + bool eventMayStartDrag(NSEvent *); - void sendFakeEventsAfterWidgetTracking(NSEvent* initiatingEvent); + void sendFakeEventsAfterWidgetTracking(NSEvent *initiatingEvent); void setActivationEventNumber(int num) { m_activationEventNumber = num; } - NSEvent *currentNSEvent(); + static NSEvent *currentNSEvent(); #endif private: @@ -201,8 +187,8 @@ private: PassRefPtr<Clipboard> createDraggingClipboard() const; bool eventActivatedView(const PlatformMouseEvent&) const; - void selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& event); - void selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& event); + void selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults&); + void selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults&); bool handleMouseDoubleClickEvent(const PlatformMouseEvent&); @@ -216,7 +202,9 @@ private: void handleKeyboardSelectionMovement(KeyboardEvent*); Cursor selectCursor(const MouseEventWithHitTestResults&, Scrollbar*); +#if ENABLE(PAN_SCROLLING) void setPanScrollCursor(); +#endif void hoverTimerFired(Timer<EventHandler>*); @@ -272,22 +260,25 @@ private: // The following are called at the beginning of handleMouseUp and handleDrag. // If they return true it indicates that they have consumed the event. -#if PLATFORM(MAC) bool eventLoopHandleMouseUp(const MouseEventWithHitTestResults&); bool eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&); - NSView *mouseDownViewIfStillGood(); -#else - bool eventLoopHandleMouseUp(const MouseEventWithHitTestResults&) { return false; } - bool eventLoopHandleMouseDragged(const MouseEventWithHitTestResults&) { return false; } -#endif bool invertSenseOfTabsToLinks(KeyboardEvent*) const; void updateSelectionForMouseDrag(Node* targetNode, const IntPoint& localPoint); + bool capturesDragging() const { return m_capturesDragging; } + +#if PLATFORM(MAC) && defined(__OBJC__) + NSView *mouseDownViewIfStillGood(); + + PlatformMouseEvent currentPlatformMouseEvent() const; +#endif + Frame* m_frame; bool m_mousePressed; + bool m_capturesDragging; RefPtr<Node> m_mousePressNode; bool m_mouseDownMayStartSelect; @@ -307,6 +298,7 @@ private: bool m_autoscrollInProgress; bool m_mouseDownMayStartAutoscroll; bool m_mouseDownWasInSubframe; + #if ENABLE(SVG) bool m_svgPan; RefPtr<SVGElementInstance> m_instanceUnderMouse; @@ -335,16 +327,12 @@ private: IntPoint m_mouseDownPos; // in our view's coords double m_mouseDownTimestamp; PlatformMouseEvent m_mouseDown; - - unsigned m_pendingFrameUnloadEventCount; - unsigned m_pendingFrameBeforeUnloadEventCount; #if PLATFORM(MAC) NSView *m_mouseDownView; bool m_sendingEventToSubview; int m_activationEventNumber; #endif - }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/FocusController.cpp b/src/3rdparty/webkit/WebCore/page/FocusController.cpp index 9b30362..8dad846 100644 --- a/src/3rdparty/webkit/WebCore/page/FocusController.cpp +++ b/src/3rdparty/webkit/WebCore/page/FocusController.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nuanti Ltd. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,6 +35,7 @@ #include "Element.h" #include "Event.h" #include "EventHandler.h" +#include "EventNames.h" #include "Frame.h" #include "FrameView.h" #include "FrameTree.h" @@ -45,6 +47,7 @@ #include "RenderObject.h" #include "RenderWidget.h" #include "SelectionController.h" +#include "Settings.h" #include "Widget.h" #include <wtf/Platform.h> @@ -63,13 +66,17 @@ void FocusController::setFocusedFrame(PassRefPtr<Frame> frame) if (m_focusedFrame == frame) return; - if (m_focusedFrame && m_focusedFrame->view()) + if (m_focusedFrame && m_focusedFrame->view()) { m_focusedFrame->selection()->setFocused(false); + m_focusedFrame->document()->dispatchWindowEvent(eventNames().blurEvent, false, false); + } m_focusedFrame = frame; - if (m_focusedFrame && m_focusedFrame->view()) + if (m_focusedFrame && m_focusedFrame->view()) { m_focusedFrame->selection()->setFocused(true); + m_focusedFrame->document()->dispatchWindowEvent(eventNames().focusEvent, false, false); + } } Frame* FocusController::focusedOrMainFrame() @@ -90,8 +97,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,12 +120,17 @@ bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* even Frame* frame = focusedOrMainFrame(); ASSERT(frame); Document* document = frame->document(); - if (!document) - return false; + + Node* currentNode = document->focusedNode(); + // FIXME: Not quite correct when it comes to focus transitions leaving/entering the WebView itself + bool caretBrowsing = focusedOrMainFrame()->settings()->caretBrowsingEnabled(); + + if (caretBrowsing && !currentNode) + currentNode = frame->selection()->start().node(); Node* node = (direction == FocusDirectionForward) - ? document->nextFocusableNode(document->focusedNode(), event) - : document->previousFocusableNode(document->focusedNode(), event); + ? document->nextFocusableNode(currentNode, event) + : document->previousFocusableNode(currentNode, event); // If there's no focusable node to advance to, move up the frame tree until we find one. while (!node && frame) { @@ -129,8 +139,6 @@ bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* even break; Document* parentDocument = parentFrame->document(); - if (!parentDocument) - break; HTMLFrameOwnerElement* owner = frame->ownerElement(); if (!owner) @@ -155,10 +163,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); @@ -201,6 +209,12 @@ bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* even if (newDocument) setFocusedFrame(newDocument->frame()); + if (caretBrowsing) { + VisibleSelection newSelection(Position(node, 0), Position(node, 0), DOWNSTREAM); + if (frame->shouldChangeSelection(newSelection)) + frame->selection()->setSelection(newSelection); + } + static_cast<Element*>(node)->focus(false); return true; } @@ -229,7 +243,11 @@ static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFram SelectionController* s = oldFocusedFrame->selection(); if (s->isNone()) return; - + + bool caretBrowsing = oldFocusedFrame->settings()->caretBrowsingEnabled(); + if (caretBrowsing) + return; + Node* selectionStartNode = s->selection().start().node(); if (selectionStartNode == newFocusedNode || selectionStartNode->isDescendantOf(newFocusedNode) || selectionStartNode->shadowAncestorNode() == newFocusedNode) return; @@ -254,7 +272,8 @@ bool FocusController::setFocusedNode(Node* node, PassRefPtr<Frame> newFocusedFra Node* oldFocusedNode = oldDocument ? oldDocument->focusedNode() : 0; if (oldFocusedNode == node) return true; - + + // FIXME: Might want to disable this check for caretBrowsing if (oldFocusedNode && oldFocusedNode->rootEditableElement() == oldFocusedNode && !relinquishesEditingFocus(oldFocusedNode)) return false; @@ -266,9 +285,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; @@ -302,6 +321,9 @@ void FocusController::setActive(bool active) } focusedOrMainFrame()->selection()->pageActivationChanged(); + + if (m_focusedFrame) + m_focusedFrame->document()->dispatchWindowEvent(active ? eventNames().focusEvent : eventNames().blurEvent, false, false); } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Frame.cpp b/src/3rdparty/webkit/WebCore/page/Frame.cpp index a4c0b57..328f321 100644 --- a/src/3rdparty/webkit/WebCore/page/Frame.cpp +++ b/src/3rdparty/webkit/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> @@ -28,11 +28,11 @@ #include "config.h" #include "Frame.h" -#include "FramePrivate.h" #include "ApplyStyleCommand.h" #include "BeforeUnloadEvent.h" #include "CSSComputedStyleDeclaration.h" +#include "CSSMutableStyleDeclaration.h" #include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CachedCSSStyleSheet.h" @@ -43,7 +43,9 @@ #include "EditorClient.h" #include "EventNames.h" #include "FocusController.h" +#include "FloatQuad.h" #include "FrameLoader.h" +#include "FrameLoaderClient.h" #include "FrameView.h" #include "GraphicsContext.h" #include "HTMLDocument.h" @@ -53,7 +55,6 @@ #include "HTMLNames.h" #include "HTMLTableCellElement.h" #include "HitTestResult.h" -#include "JSDOMWindowShell.h" #include "Logging.h" #include "markup.h" #include "MediaFeatureNames.h" @@ -67,17 +68,21 @@ #include "RenderTheme.h" #include "RenderView.h" #include "Settings.h" -#include "SystemTime.h" #include "TextIterator.h" #include "TextResourceDecoder.h" #include "XMLNames.h" #include "ScriptController.h" +#include "htmlediting.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 @@ -111,8 +116,32 @@ static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement) } Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient) - : d(new FramePrivate(page, parentFromOwnerElement(ownerElement), this, ownerElement, frameLoaderClient)) + : m_page(page) + , m_treeNode(this, parentFromOwnerElement(ownerElement)) + , m_loader(this, frameLoaderClient) + , m_ownerElement(ownerElement) + , m_script(this) + , m_selectionGranularity(CharacterGranularity) + , m_selectionController(this) + , m_caretBlinkTimer(this, &Frame::caretBlinkTimerFired) + , m_editor(this) + , m_eventHandler(this) + , m_animationController(this) + , m_lifeSupportTimer(this, &Frame::lifeSupportTimerFired) + , m_caretVisible(false) + , m_caretPaint(true) + , m_highlightTextMatches(false) + , m_inViewSourceMode(false) + , m_needsReapplyStyles(false) + , m_isDisconnected(false) + , m_excludeFromTextSearch(false) +#if FRAME_LOADS_USER_STYLESHEET + , m_userStyleSheetLoader(0) +#endif { + Frame* parent = parentFromOwnerElement(ownerElement); + m_zoomFactor = parent ? parent->m_zoomFactor : 1.0f; + AtomicString::init(); HTMLNames::init(); QualifiedName::init(); @@ -146,73 +175,66 @@ Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* Frame::~Frame() { setView(0); - loader()->clearRecordedFormValues(); loader()->cancelAndClear(); // FIXME: We should not be doing all this work inside the destructor - ASSERT(!d->m_lifeSupportTimer.isActive()); + ASSERT(!m_lifeSupportTimer.isActive()); #ifndef NDEBUG frameCounter.decrement(); #endif - if (d->m_script.haveWindowShell()) - d->m_script.windowShell()->disconnectFrame(); - disconnectOwnerElement(); - if (d->m_domWindow) - d->m_domWindow->disconnectFrame(); + if (m_domWindow) + m_domWindow->disconnectFrame(); - HashSet<DOMWindow*>::iterator end = d->m_liveFormerWindows.end(); - for (HashSet<DOMWindow*>::iterator it = d->m_liveFormerWindows.begin(); it != end; ++it) + HashSet<DOMWindow*>::iterator end = m_liveFormerWindows.end(); + for (HashSet<DOMWindow*>::iterator it = m_liveFormerWindows.begin(); it != end; ++it) (*it)->disconnectFrame(); - if (d->m_view) { - d->m_view->hide(); - d->m_view->clearFrame(); + if (m_view) { + m_view->hide(); + m_view->clearFrame(); } - ASSERT(!d->m_lifeSupportTimer.isActive()); + ASSERT(!m_lifeSupportTimer.isActive()); #if FRAME_LOADS_USER_STYLESHEET - delete d->m_userStyleSheetLoader; + delete m_userStyleSheetLoader; #endif - - delete d; - d = 0; } void Frame::init() { - d->m_loader.init(); + m_loader.init(); } FrameLoader* Frame::loader() const { - return &d->m_loader; + return &m_loader; } FrameView* Frame::view() const { - return d->m_view.get(); + return m_view.get(); } -void Frame::setView(FrameView* view) +void Frame::setView(PassRefPtr<FrameView> view) { // Detach the document now, so any onUnload handlers get run - if // we wait until the view is destroyed, then things won't be // hooked up enough for some JavaScript calls to work. - if (!view && d->m_doc && d->m_doc->attached() && !d->m_doc->inPageCache()) { + if (!view && m_doc && m_doc->attached() && !m_doc->inPageCache()) { // FIXME: We don't call willRemove here. Why is that OK? - d->m_doc->detach(); - if (d->m_view) - d->m_view->unscheduleRelayout(); + m_doc->detach(); + if (m_view) + m_view->unscheduleRelayout(); } eventHandler()->clear(); - d->m_view = view; + m_view = view; // Only one form submission is allowed per view of a part. // Since this part may be getting reused as a result of being @@ -222,40 +244,40 @@ void Frame::setView(FrameView* view) ScriptController* Frame::script() { - return &d->m_script; + return &m_script; } Document* Frame::document() const { - return d->m_doc.get(); + return m_doc.get(); } void Frame::setDocument(PassRefPtr<Document> newDoc) { - if (d->m_doc && d->m_doc->attached() && !d->m_doc->inPageCache()) { + if (m_doc && m_doc->attached() && !m_doc->inPageCache()) { // FIXME: We don't call willRemove here. Why is that OK? - d->m_doc->detach(); + m_doc->detach(); } - d->m_doc = newDoc; - if (d->m_doc && selection()->isFocusedAndActive()) - setUseSecureKeyboardEntry(d->m_doc->useSecureKeyboardEntryWhenActive()); + m_doc = newDoc; + if (m_doc && selection()->isFocusedAndActive()) + setUseSecureKeyboardEntry(m_doc->useSecureKeyboardEntryWhenActive()); - if (d->m_doc && !d->m_doc->attached()) - d->m_doc->attach(); + if (m_doc && !m_doc->attached()) + m_doc->attach(); // Update the cached 'document' property, which is now stale. - d->m_script.updateDocument(); + m_script.updateDocument(); } Settings* Frame::settings() const { - return d->m_page ? d->m_page->settings() : 0; + return m_page ? m_page->settings() : 0; } String Frame::selectedText() const { - return plainText(selection()->toRange().get()); + return plainText(selection()->toNormalizedRange().get()); } IntRect Frame::firstRectForRange(Range* range) const @@ -300,33 +322,33 @@ IntRect Frame::firstRectForRange(Range* range) const SelectionController* Frame::selection() const { - return &d->m_selectionController; + return &m_selectionController; } Editor* Frame::editor() const { - return &d->m_editor; + return &m_editor; } TextGranularity Frame::selectionGranularity() const { - return d->m_selectionGranularity; + return m_selectionGranularity; } -void Frame::setSelectionGranularity(TextGranularity granularity) const +void Frame::setSelectionGranularity(TextGranularity granularity) { - d->m_selectionGranularity = granularity; + m_selectionGranularity = granularity; } SelectionController* Frame::dragCaretController() const { - return d->m_page->dragCaretController(); + return m_page->dragCaretController(); } AnimationController* Frame::animation() const { - return &d->m_animationController; + return &m_animationController; } static RegularExpression* createRegExpForLabels(const Vector<String>& labels) @@ -334,7 +356,7 @@ static RegularExpression* createRegExpForLabels(const Vector<String>& labels) // REVIEW- version of this call in FrameMac.mm caches based on the NSArray ptrs being // the same across calls. We can't do that. - DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w")); + DEFINE_STATIC_LOCAL(RegularExpression, wordRegExp, ("\\w", TextCaseSensitive)); String pattern("("); unsigned int numLabels = labels.size(); unsigned int i; @@ -344,8 +366,8 @@ static RegularExpression* createRegExpForLabels(const Vector<String>& labels) bool startsWithWordChar = false; bool endsWithWordChar = false; if (label.length() != 0) { - startsWithWordChar = wordRegExp.search(label.substring(0, 1)) >= 0; - endsWithWordChar = wordRegExp.search(label.substring(label.length() - 1, 1)) >= 0; + startsWithWordChar = wordRegExp.match(label.substring(0, 1)) >= 0; + endsWithWordChar = wordRegExp.match(label.substring(label.length() - 1, 1)) >= 0; } if (i != 0) @@ -362,7 +384,7 @@ static RegularExpression* createRegExpForLabels(const Vector<String>& labels) } } pattern.append(")"); - return new RegularExpression(pattern, false); + return new RegularExpression(pattern, TextCaseInsensitive); } String Frame::searchForLabelsAboveCell(RegularExpression* regExp, HTMLTableCellElement* cell) @@ -374,7 +396,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 @@ -414,8 +436,7 @@ String Frame::searchForLabelsBeforeElement(const Vector<String>& labels, Element n = n->traversePreviousNode()) { if (n->hasTagName(formTag) - || (n->isHTMLElement() - && static_cast<HTMLElement*>(n)->isGenericFormElement())) + || (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement())) { // We hit another form element or the start of the form - bail out break; @@ -454,7 +475,7 @@ String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* e return String(); // Make numbers and _'s in field names behave like word boundaries, e.g., "address2" - replace(name, RegularExpression("\\d"), " "); + replace(name, RegularExpression("\\d", TextCaseSensitive), " "); name.replace('_', ' '); OwnPtr<RegularExpression> regExp(createRegExpForLabels(labels)); @@ -465,7 +486,7 @@ String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* e int bestLength = -1; int start = 0; do { - pos = regExp->search(name, start); + pos = regExp->match(name, start); if (pos != -1) { length = regExp->matchedLength(); if (length >= bestLength) { @@ -481,19 +502,19 @@ String Frame::matchLabelsAgainstElement(const Vector<String>& labels, Element* e return String(); } -const Selection& Frame::mark() const +const VisibleSelection& Frame::mark() const { - return d->m_mark; + 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()); ASSERT(!s.start().node() || s.start().node()->document() == document()); ASSERT(!s.end().node() || s.end().node()->document() == document()); - d->m_mark = s; + m_mark = s; } void Frame::notifyRendererOfSelectionChange(bool userTriggered) @@ -503,8 +524,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() @@ -515,18 +536,18 @@ void Frame::invalidateSelection() void Frame::setCaretVisible(bool flag) { - if (d->m_caretVisible == flag) + if (m_caretVisible == flag) return; clearCaretRectIfNeeded(); - d->m_caretVisible = flag; + m_caretVisible = flag; selectionLayoutChanged(); } void Frame::clearCaretRectIfNeeded() { #if ENABLE(TEXT_CARET) - if (d->m_caretPaint) { - d->m_caretPaint = false; + if (m_caretPaint) { + m_caretPaint = false; selection()->invalidateCaretRect(); } #endif @@ -547,9 +568,18 @@ static bool isFrameElement(const Node *n) void Frame::setFocusedNodeIfNeeded() { - if (!document() || selection()->isNone() || !selection()->isFocusedAndActive()) + if (selection()->isNone() || !selection()->isFocused()) return; + bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); + if (caretBrowsing) { + Node* anchor = enclosingAnchorElement(selection()->base()); + if (anchor) { + page()->focusController()->setFocusedNode(anchor, this); + return; + } + } + Node* target = selection()->rootEditableElement(); if (target) { RenderObject* renderer = target->renderer(); @@ -566,10 +596,13 @@ void Frame::setFocusedNodeIfNeeded() } renderer = renderer->parent(); if (renderer) - target = renderer->element(); + target = renderer->node(); } document()->setFocusedNode(0); } + + if (caretBrowsing) + page()->focusController()->setFocusedNode(0, this); } void Frame::selectionLayoutChanged() @@ -577,22 +610,23 @@ void Frame::selectionLayoutChanged() bool caretRectChanged = selection()->recomputeCaretRect(); #if ENABLE(TEXT_CARET) - bool shouldBlink = d->m_caretVisible - && selection()->isCaret() && selection()->isContentEditable(); + bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); + bool shouldBlink = m_caretVisible + && selection()->isCaret() && (selection()->isContentEditable() || caretBrowsing); // If the caret moved, stop the blink timer so we can restart with a // black caret in the new location. if (caretRectChanged || !shouldBlink) - d->m_caretBlinkTimer.stop(); + m_caretBlinkTimer.stop(); // Start blinking with a black caret. Be sure not to restart if we're // already blinking in the right location. - if (shouldBlink && !d->m_caretBlinkTimer.isActive()) { + if (shouldBlink && !m_caretBlinkTimer.isActive()) { if (double blinkInterval = theme()->caretBlinkInterval()) - d->m_caretBlinkTimer.startRepeating(blinkInterval); + m_caretBlinkTimer.startRepeating(blinkInterval); - if (!d->m_caretPaint) { - d->m_caretPaint = true; + if (!m_caretPaint) { + m_caretPaint = true; selection()->invalidateCaretRect(); } } @@ -605,7 +639,7 @@ void Frame::selectionLayoutChanged() if (!view) return; - Selection selection = this->selection()->selection(); + VisibleSelection selection = this->selection()->selection(); if (!selection.isRange()) view->clearSelection(); @@ -626,7 +660,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.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset()); } } } @@ -634,12 +668,12 @@ void Frame::selectionLayoutChanged() void Frame::caretBlinkTimerFired(Timer<Frame>*) { #if ENABLE(TEXT_CARET) - ASSERT(d->m_caretVisible); + ASSERT(m_caretVisible); ASSERT(selection()->isCaret()); - bool caretPaint = d->m_caretPaint; + bool caretPaint = m_caretPaint; if (selection()->isCaretBlinkingSuspended() && caretPaint) return; - d->m_caretPaint = !caretPaint; + m_caretPaint = !caretPaint; selection()->invalidateCaretRect(); #endif } @@ -647,7 +681,7 @@ void Frame::caretBlinkTimerFired(Timer<Frame>*) void Frame::paintCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const { #if ENABLE(TEXT_CARET) - if (d->m_caretPaint && d->m_caretVisible) + if (m_caretPaint && m_caretVisible) selection()->paintCaret(p, tx, ty, clipRect); #endif } @@ -655,7 +689,7 @@ void Frame::paintCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRe void Frame::paintDragCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect) const { #if ENABLE(TEXT_CARET) - SelectionController* dragCaretController = d->m_page->dragCaretController(); + SelectionController* dragCaretController = m_page->dragCaretController(); ASSERT(dragCaretController->selection().isCaret()); if (dragCaretController->selection().start().node()->document()->frame() == this) dragCaretController->paintCaret(p, tx, ty, clipRect); @@ -664,20 +698,20 @@ void Frame::paintDragCaret(GraphicsContext* p, int tx, int ty, const IntRect& cl float Frame::zoomFactor() const { - return d->m_zoomFactor; + return m_zoomFactor; } bool Frame::isZoomFactorTextOnly() const { - return d->m_page->settings()->zoomsTextOnly(); + return m_page->settings()->zoomsTextOnly(); } bool Frame::shouldApplyTextZoom() const { - if (d->m_zoomFactor == 1.0f || !isZoomFactorTextOnly()) + if (m_zoomFactor == 1.0f || !isZoomFactorTextOnly()) return false; #if ENABLE(SVG) - if (d->m_doc && d->m_doc->isSVGDocument()) + if (m_doc->isSVGDocument()) return false; #endif return true; @@ -685,10 +719,10 @@ bool Frame::shouldApplyTextZoom() const bool Frame::shouldApplyPageZoom() const { - if (d->m_zoomFactor == 1.0f || isZoomFactorTextOnly()) + if (m_zoomFactor == 1.0f || isZoomFactorTextOnly()) return false; #if ENABLE(SVG) - if (d->m_doc && d->m_doc->isSVGDocument()) + if (m_doc->isSVGDocument()) return false; #endif return true; @@ -696,45 +730,41 @@ bool Frame::shouldApplyPageZoom() const void Frame::setZoomFactor(float percent, bool isTextOnly) { - if (d->m_zoomFactor == percent && isZoomFactorTextOnly()) + if (m_zoomFactor == percent && isZoomFactorTextOnly() == isTextOnly) return; #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 (d->m_doc && d->m_doc->isSVGDocument()) { - if (!static_cast<SVGDocument*>(d->m_doc.get())->zoomAndPanEnabled()) + if (m_doc->isSVGDocument()) { + if (!static_cast<SVGDocument*>(m_doc.get())->zoomAndPanEnabled()) return; - d->m_zoomFactor = percent; - d->m_page->settings()->setZoomsTextOnly(true); // We do this to avoid doing any scaling of CSS pixels, since the SVG has its own notion of zoom. - if (d->m_doc->renderer()) - d->m_doc->renderer()->repaint(); + m_zoomFactor = percent; + m_page->settings()->setZoomsTextOnly(true); // We do this to avoid doing any scaling of CSS pixels, since the SVG has its own notion of zoom. + if (m_doc->renderer()) + m_doc->renderer()->repaint(); return; } #endif - d->m_zoomFactor = percent; - d->m_page->settings()->setZoomsTextOnly(isTextOnly); + m_zoomFactor = percent; + m_page->settings()->setZoomsTextOnly(isTextOnly); - if (d->m_doc) - d->m_doc->recalcStyle(Node::Force); + m_doc->recalcStyle(Node::Force); for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->setZoomFactor(d->m_zoomFactor, isTextOnly); + child->setZoomFactor(m_zoomFactor, isTextOnly); - if (d->m_doc && d->m_doc->renderer() && d->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 (!d->m_doc) - return; - - d->m_doc->setPrinting(printing); + m_doc->setPrinting(printing); view()->setMediaType(printing ? "print" : "screen"); - d->m_doc->updateStyleSelector(); - forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize); + m_doc->updateStyleSelector(); + view()->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, adjustViewSize); for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling()) child->setPrinting(printing, minPageWidth, maxPageWidth, adjustViewSize); @@ -742,34 +772,42 @@ void Frame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, b void Frame::setJSStatusBarText(const String& text) { - d->m_kjsStatusBarText = text; - if (d->m_page) - d->m_page->chrome()->setStatusbarText(this, d->m_kjsStatusBarText); + ASSERT(m_doc); // Client calls shouldn't be made when the frame is in inconsistent state. + m_kjsStatusBarText = text; + if (m_page) + m_page->chrome()->setStatusbarText(this, m_kjsStatusBarText); } void Frame::setJSDefaultStatusBarText(const String& text) { - d->m_kjsDefaultStatusBarText = text; - if (d->m_page) - d->m_page->chrome()->setStatusbarText(this, d->m_kjsDefaultStatusBarText); + ASSERT(m_doc); // Client calls shouldn't be made when the frame is in inconsistent state. + m_kjsDefaultStatusBarText = text; + if (m_page) + m_page->chrome()->setStatusbarText(this, m_kjsDefaultStatusBarText); } String Frame::jsStatusBarText() const { - return d->m_kjsStatusBarText; + return m_kjsStatusBarText; } String Frame::jsDefaultStatusBarText() const { - return d->m_kjsDefaultStatusBarText; + return m_kjsDefaultStatusBarText; } void Frame::setNeedsReapplyStyles() { - if (d->m_needsReapplyStyles) + // 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; - d->m_needsReapplyStyles = true; + if (m_needsReapplyStyles) + return; + + m_needsReapplyStyles = true; // FrameView's "layout" timer includes reapplyStyles, so despite its // name, it's what we want to call here. @@ -779,21 +817,19 @@ void Frame::setNeedsReapplyStyles() bool Frame::needsReapplyStyles() const { - return d->m_needsReapplyStyles; + return m_needsReapplyStyles; } void Frame::reapplyStyles() { - d->m_needsReapplyStyles = false; + 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 (d->m_doc) - d->m_doc->docLoader()->setAutoLoadImages(d->m_page && d->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 = d->m_page ? d->m_page->settings()->userStyleSheetLocation() : KURL(); + const KURL userStyleSheetLocation = m_page ? m_page->settings()->userStyleSheetLocation() : KURL(); if (!userStyleSheetLocation.isEmpty()) setUserStyleSheetLocation(userStyleSheetLocation); else @@ -804,33 +840,30 @@ 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 (d->m_doc) - d->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 (d->m_editor.clientIsEditable()) + if (m_editor.clientIsEditable()) return true; - if (!d->m_doc) - return false; - return d->m_doc->inDesignMode(); + return m_doc->inDesignMode(); } #if !PLATFORM(MAC) @@ -844,22 +877,22 @@ void Frame::setUseSecureKeyboardEntry(bool) void Frame::updateSecureKeyboardEntryIfActive() { if (selection()->isFocusedAndActive()) - setUseSecureKeyboardEntry(d->m_doc->useSecureKeyboardEntryWhenActive()); + setUseSecureKeyboardEntry(m_doc->useSecureKeyboardEntryWhenActive()); } CSSMutableStyleDeclaration *Frame::typingStyle() const { - return d->m_typingStyle.get(); + return m_typingStyle.get(); } void Frame::setTypingStyle(CSSMutableStyleDeclaration *style) { - d->m_typingStyle = style; + m_typingStyle = style; } void Frame::clearTypingStyle() { - d->m_typingStyle = 0; + m_typingStyle = 0; } void Frame::computeAndSetTypingStyle(CSSStyleDeclaration *style, EditAction editingAction) @@ -898,11 +931,11 @@ 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. - d->m_typingStyle = mutableStyle.release(); + m_typingStyle = mutableStyle.release(); } String Frame::selectionStartStylePropertyValue(int stylePropertyID) const @@ -927,13 +960,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(); @@ -943,11 +973,10 @@ PassRefPtr<CSSComputedStyleDeclaration> Frame::selectionComputedStyle(Node*& nod RefPtr<Element> styleElement = elem; ExceptionCode ec = 0; - if (d->m_typingStyle) { - styleElement = document()->createElementNS(xhtmlNamespaceURI, "span", ec); - ASSERT(ec == 0); + if (m_typingStyle) { + styleElement = document()->createElement(spanTag, false); - styleElement->setAttribute(styleAttr, d->m_typingStyle->cssText().impl(), ec); + styleElement->setAttribute(styleAttr, m_typingStyle->cssText().impl(), ec); ASSERT(ec == 0); styleElement->appendChild(document()->createEditingTextNode(""), ec); @@ -1013,10 +1042,7 @@ void Frame::textDidChangeInTextArea(Element* e) void Frame::applyEditingStyleToBodyElement() const { - if (!d->m_doc) - return; - - RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body"); + RefPtr<NodeList> list = m_doc->getElementsByTagName("body"); unsigned len = list->length(); for (unsigned i = 0; i < len; i++) { applyEditingStyleToElement(static_cast<Element*>(list->item(i))); @@ -1025,10 +1051,7 @@ void Frame::applyEditingStyleToBodyElement() const void Frame::removeEditingStyleFromBodyElement() const { - if (!d->m_doc) - return; - - RefPtr<NodeList> list = d->m_doc->getElementsByTagName("body"); + RefPtr<NodeList> list = m_doc->getElementsByTagName("body"); unsigned len = list->length(); for (unsigned i = 0; i < len; i++) { removeEditingStyleFromElement(static_cast<Element*>(list->item(i))); @@ -1066,13 +1089,13 @@ static HashSet<Frame*>& keepAliveSet() void Frame::keepAlive() { - if (d->m_lifeSupportTimer.isActive()) + if (m_lifeSupportTimer.isActive()) return; #ifndef NDEBUG keepAliveSet().add(this); #endif ref(); - d->m_lifeSupportTimer.startOneShot(0); + m_lifeSupportTimer.startOneShot(0); } #ifndef NDEBUG @@ -1081,7 +1104,7 @@ void Frame::cancelAllKeepAlive() HashSet<Frame*>::iterator end = keepAliveSet().end(); for (HashSet<Frame*>::iterator it = keepAliveSet().begin(); it != end; ++it) { Frame* frame = *it; - frame->d->m_lifeSupportTimer.stop(); + frame->m_lifeSupportTimer.stop(); frame->deref(); } keepAliveSet().clear(); @@ -1098,11 +1121,11 @@ void Frame::lifeSupportTimerFired(Timer<Frame>*) void Frame::clearDOMWindow() { - if (d->m_domWindow) { - d->m_liveFormerWindows.add(d->m_domWindow.get()); - d->m_domWindow->clear(); + if (m_domWindow) { + m_liveFormerWindows.add(m_domWindow.get()); + m_domWindow->clear(); } - d->m_domWindow = 0; + m_domWindow = 0; } RenderView* Frame::contentRenderer() const @@ -1114,17 +1137,17 @@ RenderView* Frame::contentRenderer() const if (!object) return 0; ASSERT(object->isRenderView()); - return static_cast<RenderView*>(object); + return toRenderView(object); } HTMLFrameOwnerElement* Frame::ownerElement() const { - return d->m_ownerElement; + return m_ownerElement; } RenderPart* Frame::ownerRenderer() const { - HTMLFrameOwnerElement* ownerElement = d->m_ownerElement; + HTMLFrameOwnerElement* ownerElement = m_ownerElement; if (!ownerElement) return 0; RenderObject* object = ownerElement->renderer(); @@ -1132,7 +1155,7 @@ RenderPart* Frame::ownerRenderer() const return 0; // FIXME: If <object> is ever fixed to disassociate itself from frames // that it has started but canceled, then this can turn into an ASSERT - // since d->m_ownerElement would be 0 when the load is canceled. + // since m_ownerElement would be 0 when the load is canceled. // https://bugs.webkit.org/show_bug.cgi?id=18585 if (!object->isRenderPart()) return 0; @@ -1141,29 +1164,29 @@ RenderPart* Frame::ownerRenderer() const bool Frame::isDisconnected() const { - return d->m_isDisconnected; + return m_isDisconnected; } void Frame::setIsDisconnected(bool isDisconnected) { - d->m_isDisconnected = isDisconnected; + m_isDisconnected = isDisconnected; } bool Frame::excludeFromTextSearch() const { - return d->m_excludeFromTextSearch; + return m_excludeFromTextSearch; } void Frame::setExcludeFromTextSearch(bool exclude) { - d->m_excludeFromTextSearch = exclude; + m_excludeFromTextSearch = exclude; } // returns FloatRect because going through IntRect would truncate any floats FloatRect Frame::selectionBounds(bool clipToVisibleContent) const { RenderView* root = contentRenderer(); - FrameView* view = d->m_view.get(); + FrameView* view = m_view.get(); if (!root || !view) return IntRect(); @@ -1177,13 +1200,13 @@ 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); + selectedRange->textRects(intRects, true); unsigned size = intRects.size(); - FloatRect visibleContentRect = d->m_view->visibleContentRect(); + FloatRect visibleContentRect = m_view->visibleContentRect(); for (unsigned i = 0; i < size; ++i) if (clipToVisibleContent) rects.append(intersection(intRects[i], visibleContentRect)); @@ -1192,15 +1215,6 @@ void Frame::selectionTextRects(Vector<FloatRect>& rects, bool clipToVisibleConte } -bool Frame::isFrameSet() const -{ - Document* document = d->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) { @@ -1208,7 +1222,7 @@ static HTMLFormElement *scanForForm(Node *start) for (n = start; n; n = n->traverseNextNode()) { if (n->hasTagName(formTag)) return static_cast<HTMLFormElement*>(n); - else if (n->isHTMLElement() && static_cast<HTMLElement*>(n)->isGenericFormElement()) + else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement()) return static_cast<HTMLFormControlElement*>(n)->form(); else if (n->hasTagName(frameTag) || n->hasTagName(iframeTag)) { Node *childDoc = static_cast<HTMLFrameElementBase*>(n)->contentDocument(); @@ -1223,7 +1237,7 @@ static HTMLFormElement *scanForForm(Node *start) HTMLFormElement *Frame::currentForm() const { // start looking either at the active (first responder) node, or where the selection is - Node *start = d->m_doc ? d->m_doc->focusedNode() : 0; + Node *start = m_doc ? m_doc->focusedNode() : 0; if (!start) start = selection()->start().node(); @@ -1232,8 +1246,7 @@ HTMLFormElement *Frame::currentForm() const for (n = start; n; n = n->parentNode()) { if (n->hasTagName(formTag)) return static_cast<HTMLFormElement*>(n); - else if (n->isHTMLElement() - && static_cast<HTMLElement*>(n)->isGenericFormElement()) + else if (n->isHTMLElement() && static_cast<Element*>(n)->isFormControlElement()) return static_cast<HTMLFormControlElement*>(n)->form(); } @@ -1241,66 +1254,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); @@ -1315,74 +1294,11 @@ Frame* Frame::frameForWidget(const Widget* widget) return static_cast<const FrameView*>(widget)->frame(); } -void Frame::forceLayout(bool allowSubtree) -{ - FrameView *v = d->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 = d->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) { view->unscheduleRelayout(); if (view->frame()) { - if (document && document->renderer() && document->renderer()->hasLayer()) - document->renderer()->layer()->suspendMarquees(); view->frame()->animation()->suspendAnimations(document); view->frame()->eventHandler()->stopAutoscrollTimer(); } @@ -1391,15 +1307,13 @@ void Frame::clearTimers(FrameView *view, Document *document) void Frame::clearTimers() { - clearTimers(d->m_view.get(), document()); + clearTimers(m_view.get(), document()); } RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const { nodeToRemove = 0; - if (!document()) - return 0; if (selection()->isNone()) return 0; @@ -1410,14 +1324,13 @@ RenderStyle *Frame::styleForSelectionStart(Node *&nodeToRemove) const if (!node) return 0; - if (!d->m_typingStyle) + 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); - String styleText = d->m_typingStyle->cssText() + " display: inline"; + ExceptionCode ec = 0; + String styleText = m_typingStyle->cssText() + " display: inline"; styleElement->setAttribute(styleAttr, styleText.impl(), ec); ASSERT(ec == 0); @@ -1436,42 +1349,31 @@ 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()) + bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); + if (!selection()->isNone() || !(isContentEditable() || caretBrowsing)) 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 { - return d->m_inViewSourceMode; -} - -void Frame::setInViewSourceMode(bool mode) const -{ - d->m_inViewSourceMode = mode; + return m_inViewSourceMode; } -UChar Frame::backslashAsCurrencySymbol() const +void Frame::setInViewSourceMode(bool mode) { - Document *doc = document(); - if (!doc) - return '\\'; - TextResourceDecoder *decoder = doc->decoder(); - if (!decoder) - return '\\'; - - return decoder->encoding().backslashAsCurrencySymbol(); + m_inViewSourceMode = 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()) @@ -1480,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()); @@ -1500,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()); @@ -1550,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())); @@ -1600,13 +1502,13 @@ 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 && d->m_view && contentRenderer()) { + if (m_view && contentRenderer()) { doc->updateLayout(); // Ensure layout is up to date. - IntRect visibleRect = d->m_view->visibleContentRect(); + IntRect visibleRect = m_view->visibleContentRect(); if (!visibleRect.isEmpty()) { GraphicsContext context((PlatformGraphicsContext*)0); context.setPaintingDisabled(true); - d->m_view->paintContents(&context, visibleRect); + m_view->paintContents(&context, visibleRect); } } @@ -1615,53 +1517,53 @@ unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsig bool Frame::markedTextMatchesAreHighlighted() const { - return d->m_highlightTextMatches; + return m_highlightTextMatches; } void Frame::setMarkedTextMatchesAreHighlighted(bool flag) { - if (flag == d->m_highlightTextMatches || !document()) + if (flag == m_highlightTextMatches) return; - d->m_highlightTextMatches = flag; + m_highlightTextMatches = flag; document()->repaintMarkers(DocumentMarker::TextMatch); } FrameTree* Frame::tree() const { - return &d->m_treeNode; + return &m_treeNode; } void Frame::setDOMWindow(DOMWindow* domWindow) { - if (d->m_domWindow) { - d->m_liveFormerWindows.add(d->m_domWindow.get()); - d->m_domWindow->clear(); + if (m_domWindow) { + m_liveFormerWindows.add(m_domWindow.get()); + m_domWindow->clear(); } - d->m_domWindow = domWindow; + m_domWindow = domWindow; } DOMWindow* Frame::domWindow() const { - if (!d->m_domWindow) - d->m_domWindow = DOMWindow::create(const_cast<Frame*>(this)); + if (!m_domWindow) + m_domWindow = DOMWindow::create(const_cast<Frame*>(this)); - return d->m_domWindow.get(); + return m_domWindow.get(); } void Frame::clearFormerDOMWindow(DOMWindow* window) { - d->m_liveFormerWindows.remove(window); + m_liveFormerWindows.remove(window); } Page* Frame::page() const { - return d->m_page; + return m_page; } EventHandler* Frame::eventHandler() const { - return &d->m_eventHandler; + return &m_eventHandler; } void Frame::pageDestroyed() @@ -1675,35 +1577,28 @@ void Frame::pageDestroyed() page()->focusController()->setFocusedFrame(0); script()->clearWindowShell(); - - // This will stop any JS timers - if (script()->haveWindowShell()) - script()->windowShell()->disconnectFrame(); - script()->clearScriptObjects(); script()->updatePlatformScriptObjects(); - d->m_page = 0; + m_page = 0; } void Frame::disconnectOwnerElement() { - if (d->m_ownerElement) { + if (m_ownerElement) { if (Document* doc = document()) doc->clearAXObjectCache(); - d->m_ownerElement->m_contentFrame = 0; - if (d->m_page) - d->m_page->decrementFrameCount(); + m_ownerElement->m_contentFrame = 0; + if (m_page) + m_page->decrementFrameCount(); } - d->m_ownerElement = 0; + m_ownerElement = 0; } 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(); } @@ -1730,31 +1625,28 @@ void Frame::unfocusWindow() page()->chrome()->unfocus(); } -bool Frame::shouldClose() +bool Frame::shouldClose(RegisteredEventListenerVector* alternateEventListeners) { Chrome* chrome = page() ? page()->chrome() : 0; if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel()) return true; - RefPtr<Document> doc = document(); - if (!doc) + if (!m_domWindow) return true; + + RefPtr<Document> doc = document(); HTMLElement* body = doc->body(); if (!body) return true; - RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create(); - beforeUnloadEvent->setTarget(doc); - doc->handleWindowEvent(beforeUnloadEvent.get(), false); + RefPtr<BeforeUnloadEvent> beforeUnloadEvent = m_domWindow->dispatchBeforeUnloadEvent(alternateEventListeners); - if (!beforeUnloadEvent->defaultPrevented() && doc) + if (!beforeUnloadEvent->defaultPrevented()) doc->defaultEventHandler(beforeUnloadEvent.get()); if (beforeUnloadEvent->result().isNull()) return true; - String text = beforeUnloadEvent->result(); - text.replace('\\', backslashAsCurrencySymbol()); - + String text = doc->displayStringModifiedByEncoding(beforeUnloadEvent->result()); return chrome->runBeforeUnloadConfirmPanel(text, this); } @@ -1768,52 +1660,51 @@ 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; + bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); + if (selection()->selection().isContentEditable() || caretBrowsing) { + 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); } @@ -1826,7 +1717,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; @@ -1844,37 +1735,46 @@ Document* Frame::documentAtPoint(const IntPoint& point) result = eventHandler()->hitTestResultAtPoint(pt, false); return result.innerNode() ? result.innerNode()->document() : 0; } - -FramePrivate::FramePrivate(Page* page, Frame* parent, Frame* thisFrame, HTMLFrameOwnerElement* ownerElement, - FrameLoaderClient* frameLoaderClient) - : m_page(page) - , m_treeNode(thisFrame, parent) - , m_loader(thisFrame, frameLoaderClient) - , m_ownerElement(ownerElement) - , m_script(thisFrame) - , m_zoomFactor(parent ? parent->d->m_zoomFactor : 1.0f) - , m_selectionGranularity(CharacterGranularity) - , m_selectionController(thisFrame) - , m_caretBlinkTimer(thisFrame, &Frame::caretBlinkTimerFired) - , m_editor(thisFrame) - , m_eventHandler(thisFrame) - , m_animationController(thisFrame) - , m_lifeSupportTimer(thisFrame, &Frame::lifeSupportTimerFired) - , m_caretVisible(false) - , m_caretPaint(true) - , m_highlightTextMatches(false) - , m_inViewSourceMode(false) - , m_needsReapplyStyles(false) - , m_isDisconnected(false) - , m_excludeFromTextSearch(false) -#if FRAME_LOADS_USER_STYLESHEET - , m_userStyleSheetLoader(0) -#endif -{ -} -FramePrivate::~FramePrivate() +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); + + RefPtr<FrameView> frameView; + if (isMainFrame) { + frameView = FrameView::create(this, viewportSize); + frameView->setFixedLayoutSize(fixedLayoutSize); + frameView->setUseFixedLayout(useFixedLayout); + } else + frameView = FrameView::create(this); + + frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode); + frameView->updateDefaultScrollbarState(); + + setView(frameView); + + if (backgroundColor.isValid()) + frameView->updateBackgroundRecursively(backgroundColor, transparent); + + if (isMainFrame) + frameView->setParentVisible(true); + + if (ownerRenderer()) + ownerRenderer()->setWidget(frameView.get()); + + if (HTMLFrameOwnerElement* owner = ownerElement()) + view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Frame.h b/src/3rdparty/webkit/WebCore/page/Frame.h index 874d90d..0a44a6d 100644 --- a/src/3rdparty/webkit/WebCore/page/Frame.h +++ b/src/3rdparty/webkit/WebCore/page/Frame.h @@ -5,7 +5,7 @@ * 2000-2001 Simon Hausmann <hausmann@kde.org> * 2000-2001 Dirk Mueller <mueller@kde.org> * 2000 Stefan Schimanski <1Stein@gmx.de> - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2008 Eric Seidel <eric@webkit.org> * @@ -28,11 +28,24 @@ #ifndef Frame_h #define Frame_h +#include "AnimationController.h" +#include "Document.h" #include "DragImage.h" #include "EditAction.h" -#include "RenderLayer.h" +#include "Editor.h" +#include "EventHandler.h" +#include "FrameLoader.h" +#include "FrameTree.h" +#include "Range.h" +#include "ScrollBehavior.h" +#include "ScriptController.h" +#include "SelectionController.h" #include "TextGranularity.h" +#if PLATFORM(WIN) +#include "FrameWin.h" +#endif + #if PLATFORM(MAC) #ifndef __OBJC__ class NSArray; @@ -49,21 +62,27 @@ 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 + class UserStyleSheetLoader; +#endif + template <typename T> class Timer; class Frame : public RefCounted<Frame> { @@ -72,7 +91,7 @@ public: { return adoptRef(new Frame(page, ownerElement, client)); } - void setView(FrameView*); + void setView(PassRefPtr<FrameView>); ~Frame(); void init(); @@ -106,12 +125,12 @@ 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*); - - FramePrivate* d; // === undecided, would like to consider moving to another class @@ -128,7 +147,7 @@ public: void setPrinting(bool printing, float minPageWidth, float maxPageWidth, bool adjustViewSize); bool inViewSourceMode() const; - void setInViewSourceMode(bool = true) const; + void setInViewSourceMode(bool = true); void keepAlive(); // Used to keep the frame alive when running a script that might destroy it. #ifndef NDEBUG @@ -140,9 +159,6 @@ public: void clearTimers(); static void clearTimers(FrameView*, Document*); - // Convenience, to avoid repeating the code to dig down to get this. - UChar backslashAsCurrencySymbol() const; - void setNeedsReapplyStyles(); bool needsReapplyStyles() const; void reapplyStyles(); @@ -153,28 +169,17 @@ public: // should move onto ScriptController void clearDOMWindow(); + String displayStringModifiedByEncoding(const String& str) const + { + return document() ? document()->displayStringModifiedByEncoding(str) : str; + } + 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; @@ -188,7 +193,7 @@ public: public: void focusWindow(); void unfocusWindow(); - bool shouldClose(); + bool shouldClose(RegisteredEventListenerVector* alternateEventListeners = 0); void scheduleClose(); void setJSStatusBarText(const String&); @@ -202,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; @@ -214,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; @@ -238,10 +243,10 @@ public: public: TextGranularity selectionGranularity() const; - void setSelectionGranularity(TextGranularity) 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(); @@ -266,8 +271,7 @@ public: 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); @@ -321,6 +325,51 @@ public: #endif +private: + Page* m_page; + mutable FrameTree m_treeNode; + mutable FrameLoader m_loader; + + mutable RefPtr<DOMWindow> m_domWindow; + HashSet<DOMWindow*> m_liveFormerWindows; + + HTMLFrameOwnerElement* m_ownerElement; + RefPtr<FrameView> m_view; + RefPtr<Document> m_doc; + + ScriptController m_script; + + String m_kjsStatusBarText; + String m_kjsDefaultStatusBarText; + + float m_zoomFactor; + + TextGranularity m_selectionGranularity; + + mutable SelectionController m_selectionController; + mutable VisibleSelection m_mark; + Timer<Frame> m_caretBlinkTimer; + mutable Editor m_editor; + mutable EventHandler m_eventHandler; + mutable AnimationController m_animationController; + + RefPtr<CSSMutableStyleDeclaration> m_typingStyle; + + Timer<Frame> m_lifeSupportTimer; + + bool m_caretVisible; + bool m_caretPaint; + + bool m_highlightTextMatches; + bool m_inViewSourceMode; + bool m_needsReapplyStyles; + bool m_isDisconnected; + bool m_excludeFromTextSearch; + +#if FRAME_LOADS_USER_STYLESHEET + UserStyleSheetLoader* m_userStyleSheetLoader; +#endif + }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/FrameLoadRequest.h b/src/3rdparty/webkit/WebCore/page/FrameLoadRequest.h index 99f415f..b84a1ec 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameLoadRequest.h +++ b/src/3rdparty/webkit/WebCore/page/FrameLoadRequest.h @@ -33,20 +33,17 @@ namespace WebCore { struct FrameLoadRequest { public: FrameLoadRequest() - : m_lockHistory(false) { } FrameLoadRequest(const ResourceRequest& resourceRequest) : m_resourceRequest(resourceRequest) - , m_lockHistory(false) { } FrameLoadRequest(const ResourceRequest& resourceRequest, const String& frameName) : m_resourceRequest(resourceRequest) , m_frameName(frameName) - , m_lockHistory(false) { } @@ -58,13 +55,9 @@ namespace WebCore { const String& frameName() const { return m_frameName; } void setFrameName(const String& frameName) { m_frameName = frameName; } - bool lockHistory() const { return m_lockHistory; } - void setLockHistory(bool lock) { m_lockHistory = lock; } - private: ResourceRequest m_resourceRequest; String m_frameName; - bool m_lockHistory; }; } diff --git a/src/3rdparty/webkit/WebCore/page/FramePrivate.h b/src/3rdparty/webkit/WebCore/page/FramePrivate.h deleted file mode 100644 index 2f7c59a..0000000 --- a/src/3rdparty/webkit/WebCore/page/FramePrivate.h +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> - * 1999-2001 Lars Knoll <knoll@kde.org> - * 1999-2001 Antti Koivisto <koivisto@kde.org> - * 2000-2001 Simon Hausmann <hausmann@kde.org> - * 2000-2001 Dirk Mueller <mueller@kde.org> - * 2000 Stefan Schimanski <1Stein@gmx.de> - * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef FramePrivate_h -#define FramePrivate_h - -#include "AnimationController.h" -#include "Editor.h" -#include "EventHandler.h" -#include "FrameLoader.h" -#include "FrameTree.h" -#include "Range.h" -#include "SelectionController.h" -#include "StringHash.h" -#include "ScriptController.h" - -#if PLATFORM(WIN) -#include "FrameWin.h" -#endif - -namespace WebCore { - -#if FRAME_LOADS_USER_STYLESHEET - class UserStyleSheetLoader; -#endif - - class FramePrivate { - public: - FramePrivate(Page*, Frame* parent, Frame* thisFrame, HTMLFrameOwnerElement*, FrameLoaderClient*); - ~FramePrivate(); - - Page* m_page; - FrameTree m_treeNode; - FrameLoader m_loader; - RefPtr<DOMWindow> m_domWindow; - HashSet<DOMWindow*> m_liveFormerWindows; - - HTMLFrameOwnerElement* m_ownerElement; - RefPtr<FrameView> m_view; - RefPtr<Document> m_doc; - - ScriptController m_script; - - String m_kjsStatusBarText; - String m_kjsDefaultStatusBarText; - - float m_zoomFactor; - - TextGranularity m_selectionGranularity; - - SelectionController m_selectionController; - Selection m_mark; - Timer<Frame> m_caretBlinkTimer; - Editor m_editor; - EventHandler m_eventHandler; - AnimationController m_animationController; - - RefPtr<CSSMutableStyleDeclaration> m_typingStyle; - - Timer<Frame> m_lifeSupportTimer; - - bool m_caretVisible; - bool m_caretPaint; - - bool m_highlightTextMatches; - bool m_inViewSourceMode; - bool m_needsReapplyStyles; - bool m_isDisconnected; - bool m_excludeFromTextSearch; - -#if FRAME_LOADS_USER_STYLESHEET - UserStyleSheetLoader* m_userStyleSheetLoader; -#endif - }; -} - -#endif diff --git a/src/3rdparty/webkit/WebCore/page/FrameTree.cpp b/src/3rdparty/webkit/WebCore/page/FrameTree.cpp index c9b4172..24f125d 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameTree.cpp +++ b/src/3rdparty/webkit/WebCore/page/FrameTree.cpp @@ -21,6 +21,7 @@ #include "FrameTree.h" #include "Frame.h" +#include "FrameView.h" #include "Page.h" #include "PageGroup.h" #include <stdarg.h> @@ -82,10 +83,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/src/3rdparty/webkit/WebCore/page/FrameTree.h b/src/3rdparty/webkit/WebCore/page/FrameTree.h index 0952dcd..d4c8c43 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameTree.h +++ b/src/3rdparty/webkit/WebCore/page/FrameTree.h @@ -21,10 +21,11 @@ #define FrameTree_h #include "AtomicString.h" -#include "Frame.h" namespace WebCore { + class Frame; + class FrameTree : Noncopyable { public: FrameTree(Frame* thisFrame, Frame* parentFrame) @@ -55,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/src/3rdparty/webkit/WebCore/page/FrameView.cpp b/src/3rdparty/webkit/WebCore/page/FrameView.cpp index 4d765ac..f6501be 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameView.cpp +++ b/src/3rdparty/webkit/WebCore/page/FrameView.cpp @@ -29,6 +29,7 @@ #include "AXObjectCache.h" #include "CSSStyleSelector.h" #include "ChromeClient.h" +#include "DocLoader.h" #include "EventHandler.h" #include "FloatRect.h" #include "FocusController.h" @@ -49,7 +50,11 @@ #include "RenderTheme.h" #include "RenderView.h" #include "Settings.h" -#include "SystemTime.h" +#include <wtf/CurrentTime.h> + +#if USE(ACCELERATED_COMPOSITING) +#include "RenderLayerCompositor.h" +#endif namespace WebCore { @@ -57,160 +62,129 @@ using namespace HTMLNames; double FrameView::sCurrentPaintTimeStamp = 0.0; -struct ScheduledEvent { - RefPtr<Event> m_event; - RefPtr<EventTargetNode> m_eventTarget; -}; - -class FrameViewPrivate { -public: - FrameViewPrivate(FrameView* view) - : m_slowRepaintObjectCount(0) - , m_layoutTimer(view, &FrameView::layoutTimerFired) - , m_layoutRoot(0) - , m_postLayoutTasksTimer(view, &FrameView::postLayoutTimerFired) - , m_mediaType("screen") - , m_enqueueEvents(0) - , m_overflowStatusDirty(true) - , m_viewportRenderer(0) - , m_wasScrolledByUser(false) - , m_inProgrammaticScroll(false) - , m_shouldUpdateWhileOffscreen(true) - { - m_isTransparent = false; - m_baseBackgroundColor = Color::white; - m_vmode = m_hmode = ScrollbarAuto; - m_needToInitScrollbars = true; - reset(); - } - void reset() - { - m_useSlowRepaints = false; - m_borderX = 30; - m_borderY = 30; - m_layoutTimer.stop(); - m_layoutRoot = 0; - m_delayedLayout = false; - m_doFullRepaint = true; - m_layoutSchedulingEnabled = true; - m_midLayout = false; - m_layoutCount = 0; - m_nestedLayoutCount = 0; - m_postLayoutTasksTimer.stop(); - m_firstLayout = true; - m_firstLayoutCallbackPending = false; - m_wasScrolledByUser = false; - m_lastLayoutSize = IntSize(); - m_lastZoomFactor = 1.0f; - m_deferringRepaints = 0; - m_repaintCount = 0; - m_repaintRect = IntRect(); - m_repaintRects.clear(); - m_paintRestriction = PaintRestrictionNone; - m_isPainting = false; - m_isVisuallyNonEmpty = false; - m_firstVisuallyNonEmptyLayoutCallbackPending = true; - } - - bool m_doFullRepaint; - - ScrollbarMode m_vmode; - ScrollbarMode m_hmode; - bool m_useSlowRepaints; - unsigned m_slowRepaintObjectCount; - - int m_borderX, m_borderY; - - Timer<FrameView> m_layoutTimer; - bool m_delayedLayout; - RenderObject* m_layoutRoot; - - bool m_layoutSchedulingEnabled; - bool m_midLayout; - int m_layoutCount; - unsigned m_nestedLayoutCount; - Timer<FrameView> m_postLayoutTasksTimer; - bool m_firstLayoutCallbackPending; - - bool m_firstLayout; - bool m_needToInitScrollbars; - bool m_isTransparent; - Color m_baseBackgroundColor; - IntSize m_lastLayoutSize; - float m_lastZoomFactor; - - String m_mediaType; - - unsigned m_enqueueEvents; - Vector<ScheduledEvent*> m_scheduledEvents; - - bool m_overflowStatusDirty; - bool m_horizontalOverflow; - bool m_verticalOverflow; - RenderObject* m_viewportRenderer; - - bool m_wasScrolledByUser; - bool m_inProgrammaticScroll; - - unsigned m_deferringRepaints; - unsigned m_repaintCount; - IntRect m_repaintRect; - Vector<IntRect> m_repaintRects; - - bool m_shouldUpdateWhileOffscreen; +#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 - RefPtr<Node> m_nodeToDraw; - PaintRestriction m_paintRestriction; - bool m_isPainting; +// The maximum number of updateWidgets iterations that should be done before returning. +static const unsigned maxUpdateWidgetsIterations = 2; - bool m_isVisuallyNonEmpty; - bool m_firstVisuallyNonEmptyLayoutCallbackPending; +struct ScheduledEvent { + RefPtr<Event> m_event; + RefPtr<Node> m_eventTarget; }; FrameView::FrameView(Frame* frame) - : m_refCount(1) - , m_frame(frame) - , d(new FrameViewPrivate(this)) + : m_frame(frame) + , m_vmode(ScrollbarAuto) + , m_hmode(ScrollbarAuto) + , m_slowRepaintObjectCount(0) + , m_layoutTimer(this, &FrameView::layoutTimerFired) + , m_layoutRoot(0) + , m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired) + , m_needToInitScrollbars(true) + , m_isTransparent(false) + , m_baseBackgroundColor(Color::white) + , m_mediaType("screen") + , m_enqueueEvents(0) + , m_overflowStatusDirty(true) + , m_viewportRenderer(0) + , m_wasScrolledByUser(false) + , m_inProgrammaticScroll(false) + , m_deferredRepaintTimer(this, &FrameView::deferredRepaintTimerFired) + , m_shouldUpdateWhileOffscreen(true) + , m_deferSetNeedsLayouts(0) + , m_setNeedsLayoutWasDeferred(false) + , m_lockedToAnchor(false) { init(); - show(); } -FrameView::FrameView(Frame* frame, const IntSize& initialSize) - : m_refCount(1) - , m_frame(frame) - , d(new FrameViewPrivate(this)) +PassRefPtr<FrameView> FrameView::create(Frame* frame) { - init(); - Widget::setFrameRect(IntRect(x(), y(), initialSize.width(), initialSize.height())); - show(); + RefPtr<FrameView> view = adoptRef(new FrameView(frame)); + view->show(); + return view.release(); +} + +PassRefPtr<FrameView> FrameView::create(Frame* frame, const IntSize& initialSize) +{ + RefPtr<FrameView> view = adoptRef(new FrameView(frame)); + view->Widget::setFrameRect(IntRect(view->pos(), initialSize)); + view->show(); + return view.release(); } FrameView::~FrameView() { - if (d->m_postLayoutTasksTimer.isActive()) { - d->m_postLayoutTasksTimer.stop(); - d->m_scheduledEvents.clear(); - d->m_enqueueEvents = 0; + if (m_postLayoutTasksTimer.isActive()) { + m_postLayoutTasksTimer.stop(); + m_scheduledEvents.clear(); + m_enqueueEvents = 0; } resetScrollbars(); setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow. setHasVerticalScrollbar(false); - ASSERT(m_refCount == 0); - ASSERT(d->m_scheduledEvents.isEmpty()); - ASSERT(!d->m_enqueueEvents); + ASSERT(m_scheduledEvents.isEmpty()); + 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); } +} - delete d; - d = 0; +void FrameView::reset() +{ + m_useSlowRepaints = false; + m_isOverlapped = false; + m_contentIsOpaque = false; + m_borderX = 30; + m_borderY = 30; + m_layoutTimer.stop(); + m_layoutRoot = 0; + m_delayedLayout = false; + m_doFullRepaint = true; + m_layoutSchedulingEnabled = true; + m_midLayout = false; + m_layoutCount = 0; + m_nestedLayoutCount = 0; + m_postLayoutTasksTimer.stop(); + m_firstLayout = true; + m_firstLayoutCallbackPending = false; + m_wasScrolledByUser = false; + m_lastLayoutSize = IntSize(); + m_lastZoomFactor = 1.0f; + m_deferringRepaints = 0; + m_repaintCount = 0; + m_repaintRects.clear(); + m_deferredRepaintDelay = initialDeferredRepaintDelayDuringLoading; + m_deferredRepaintTimer.stop(); + m_lastPaintTime = 0; + m_paintRestriction = PaintRestrictionNone; + m_isPainting = false; + m_isVisuallyNonEmpty = false; + m_firstVisuallyNonEmptyLayoutCallbackPending = true; + m_lockedToAnchor = false; } bool FrameView::isFrameView() const @@ -226,14 +200,16 @@ void FrameView::clearFrame() void FrameView::resetScrollbars() { // Reset the document's scrollbars back to our defaults before we yield the floor. - d->m_firstLayout = true; + m_firstLayout = true; setScrollbarsSuppressed(true); - setScrollbarModes(d->m_hmode, d->m_vmode); + setScrollbarModes(m_hmode, m_vmode); setScrollbarsSuppressed(false); } void FrameView::init() { + reset(); + m_margins = IntSize(-1, -1); // undefined m_size = IntSize(); @@ -256,33 +232,34 @@ void FrameView::clear() { setCanBlitOnScroll(true); - d->reset(); + reset(); - if (m_frame) + if (m_frame) { if (RenderPart* renderer = m_frame->ownerRenderer()) renderer->viewCleared(); + } setScrollbarsSuppressed(true); } bool FrameView::didFirstLayout() const { - return !d->m_firstLayout; + return !m_firstLayout; } void FrameView::initScrollbars() { - if (!d->m_needToInitScrollbars) + if (!m_needToInitScrollbars) return; - d->m_needToInitScrollbars = false; + m_needToInitScrollbars = false; updateDefaultScrollbarState(); } void FrameView::updateDefaultScrollbarState() { - d->m_hmode = horizontalScrollbarMode(); - d->m_vmode = verticalScrollbarMode(); - setScrollbarModes(d->m_hmode, d->m_vmode); + m_hmode = horizontalScrollbarMode(); + m_vmode = verticalScrollbarMode(); + setScrollbarModes(m_hmode, m_vmode); } void FrameView::invalidateRect(const IntRect& rect) @@ -321,29 +298,27 @@ void FrameView::setMarginHeight(int h) void FrameView::setCanHaveScrollbars(bool canScroll) { ScrollView::setCanHaveScrollbars(canScroll); - scrollbarModes(d->m_hmode, d->m_vmode); + scrollbarModes(m_hmode, m_vmode); } PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientation) { // 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)) - return RenderScrollbar::createCustomScrollbar(this, orientation, body->renderer()); + Element* body = doc ? doc->body() : 0; + 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)) - return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderer()); + Element* docElement = doc ? doc->documentElement() : 0; + 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. @@ -352,6 +327,8 @@ PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientatio void FrameView::setContentsSize(const IntSize& size) { + m_deferSetNeedsLayouts++; + ScrollView::setContentsSize(size); Page* page = frame() ? frame()->page() : 0; @@ -359,6 +336,11 @@ void FrameView::setContentsSize(const IntSize& size) return; page->chrome()->contentsSizeChanged(frame(), size); //notify only + + m_deferSetNeedsLayouts--; + + if (!m_deferSetNeedsLayouts) + m_setNeedsLayoutWasDeferred = false; // FIXME: Find a way to make the deferred layout actually happen. } void FrameView::adjustViewSize() @@ -406,31 +388,57 @@ void FrameView::applyOverflowToViewport(RenderObject* o, ScrollbarMode& hMode, S ; } - d->m_viewportRenderer = o; + 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(); } -int FrameView::layoutCount() const +void FrameView::setNeedsOneShotDrawingSynchronization() { - return d->m_layoutCount; + Page* page = frame() ? frame()->page() : 0; + if (page) + page->chrome()->client()->setNeedsOneShotDrawingSynchronization(); } +#endif // USE(ACCELERATED_COMPOSITING) -bool FrameView::needsFullRepaint() const +void FrameView::didMoveOnscreen() { - return d->m_doFullRepaint; + 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 : d->m_layoutRoot; + return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot; } void FrameView::layout(bool allowSubtree) { - if (d->m_midLayout) + if (m_midLayout) return; - d->m_layoutTimer.stop(); - d->m_delayedLayout = false; + m_layoutTimer.stop(); + m_delayedLayout = false; + m_setNeedsLayoutWasDeferred = false; // Protect the view from being deleted during layout (in recalcStyle) RefPtr<FrameView> protector(this); @@ -447,9 +455,9 @@ void FrameView::layout(bool allowSubtree) if (isPainting()) return; - if (!allowSubtree && d->m_layoutRoot) { - d->m_layoutRoot->markContainingBlocksForLayout(false); - d->m_layoutRoot = 0; + if (!allowSubtree && m_layoutRoot) { + m_layoutRoot->markContainingBlocksForLayout(false); + m_layoutRoot = 0; } ASSERT(m_frame->view() == this); @@ -460,18 +468,13 @@ 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; - } - d->m_layoutSchedulingEnabled = false; + m_layoutSchedulingEnabled = false; - if (!d->m_nestedLayoutCount && d->m_postLayoutTasksTimer.isActive()) { + if (!m_nestedLayoutCount && m_postLayoutTasksTimer.isActive()) { // This is a new top-level layout. If there are any remaining tasks from the previous // layout, finish them now. - d->m_postLayoutTasksTimer.stop(); + m_postLayoutTasksTimer.stop(); performPostLayoutTasks(); } @@ -484,27 +487,27 @@ void FrameView::layout(bool allowSubtree) // the layout beats any sort of style recalc update that needs to occur. if (m_frame->needsReapplyStyles()) m_frame->reapplyStyles(); - else if (document->hasChangedChild()) + else if (document->childNeedsStyleRecalc()) document->recalcStyle(); - bool subtree = d->m_layoutRoot; + bool subtree = m_layoutRoot; // If there is only one ref to this view left, then its going to be destroyed as soon as we exit, // so there's no point to continuing to layout if (protector->hasOneRef()) return; - RenderObject* root = subtree ? d->m_layoutRoot : document->renderer(); + RenderObject* root = subtree ? m_layoutRoot : document->renderer(); if (!root) { // FIXME: Do we need to set m_size here? - d->m_layoutSchedulingEnabled = true; + m_layoutSchedulingEnabled = true; return; } - d->m_nestedLayoutCount++; + m_nestedLayoutCount++; - ScrollbarMode hMode = d->m_hmode; - ScrollbarMode vMode = d->m_vmode; + ScrollbarMode hMode = m_hmode; + ScrollbarMode vMode = m_vmode; if (!subtree) { RenderObject* rootRenderer = document->documentElement() ? document->documentElement()->renderer() : 0; @@ -515,8 +518,8 @@ void FrameView::layout(bool allowSubtree) vMode = ScrollbarAlwaysOff; hMode = ScrollbarAlwaysOff; } else if (body->hasTagName(bodyTag)) { - if (!d->m_firstLayout && m_size.height() != layoutHeight() - && static_cast<RenderBox*>(body->renderer())->stretchesToViewHeight()) + if (!m_firstLayout && m_size.height() != layoutHeight() + && toRenderBox(body->renderer())->stretchesToViewHeight()) body->renderer()->setChildNeedsLayout(true); // It's sufficient to just check the X overflow, // since it's illegal to have visible in only one direction. @@ -526,25 +529,25 @@ void FrameView::layout(bool allowSubtree) } else if (rootRenderer) applyOverflowToViewport(rootRenderer, hMode, vMode); #ifdef INSTRUMENT_LAYOUT_SCHEDULING - if (d->m_firstLayout && !document->ownerElement()) + if (m_firstLayout && !document->ownerElement()) printf("Elapsed time before first layout: %d\n", document->elapsedTime()); #endif } - d->m_doFullRepaint = !subtree && (d->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. ScrollbarMode currentHMode = horizontalScrollbarMode(); ScrollbarMode currentVMode = verticalScrollbarMode(); - if (d->m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) { + if (m_firstLayout || (hMode != currentHMode || vMode != currentVMode)) { setScrollbarsSuppressed(true); - if (d->m_firstLayout) { - d->m_firstLayout = false; - d->m_firstLayoutCallbackPending = true; - d->m_lastLayoutSize = IntSize(width(), height()); - d->m_lastZoomFactor = root->style()->zoom(); + if (m_firstLayout) { + m_firstLayout = false; + m_firstLayoutCallbackPending = true; + m_lastLayoutSize = IntSize(width(), height()); + m_lastZoomFactor = root->style()->zoom(); // Set the initial vMode to AlwaysOn if we're auto. if (vMode == ScrollbarAuto) @@ -562,7 +565,7 @@ void FrameView::layout(bool allowSubtree) m_size = IntSize(layoutWidth(), layoutHeight()); if (oldSize != m_size) - d->m_doFullRepaint = true; + m_doFullRepaint = true; } RenderLayer* layer = root->enclosingLayer(); @@ -572,33 +575,37 @@ void FrameView::layout(bool allowSubtree) if (subtree) root->view()->pushLayoutState(root); - d->m_midLayout = true; + m_midLayout = true; beginDeferredRepaints(); root->layout(); endDeferredRepaints(); - d->m_midLayout = false; + m_midLayout = false; if (subtree) root->view()->popLayoutState(); - d->m_layoutRoot = 0; + m_layoutRoot = 0; m_frame->invalidateSelection(); - d->m_layoutSchedulingEnabled = true; + 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(d->m_doFullRepaint); + layer->updateLayerPositions(m_doFullRepaint); endDeferredRepaints(); + +#if USE(ACCELERATED_COMPOSITING) + updateCompositingLayers(); +#endif - d->m_layoutCount++; + m_layoutCount++; #if PLATFORM(MAC) if (AXObjectCache::accessibilityEnabled()) - root->document()->axObjectCache()->postNotificationToElement(root, "AXLayoutComplete"); + root->document()->axObjectCache()->postNotification(root, "AXLayoutComplete", true); #endif #if ENABLE(DASHBOARD_SUPPORT) updateDashboardRegions(); @@ -612,24 +619,27 @@ void FrameView::layout(bool allowSubtree) updateOverflowStatus(layoutWidth() < contentsWidth(), layoutHeight() < contentsHeight()); - if (!d->m_postLayoutTasksTimer.isActive()) { + if (!m_postLayoutTasksTimer.isActive()) { // 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. - d->m_postLayoutTasksTimer.startOneShot(0); + m_postLayoutTasksTimer.startOneShot(0); pauseScheduledEvents(); layout(); } } else { resumeScheduledEvents(); - ASSERT(d->m_enqueueEvents); + ASSERT(m_enqueueEvents); } - d->m_nestedLayoutCount--; + if (lockedToAnchor()) + m_frame->loader()->gotoAnchor(); + + m_nestedLayoutCount--; } void FrameView::addWidgetToUpdate(RenderPartObject* object) @@ -650,7 +660,7 @@ void FrameView::removeWidgetToUpdate(RenderPartObject* object) void FrameView::setMediaType(const String& mediaType) { - d->m_mediaType = mediaType; + m_mediaType = mediaType; } String FrameView::mediaType() const @@ -659,33 +669,51 @@ String FrameView::mediaType() const String overrideType = m_frame->loader()->client()->overrideMediaType(); if (!overrideType.isNull()) return overrideType; - return d->m_mediaType; + return m_mediaType; } bool FrameView::useSlowRepaints() const { - return d->m_useSlowRepaints || d->m_slowRepaintObjectCount > 0; + return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || m_isOverlapped || !m_contentIsOpaque; } void FrameView::setUseSlowRepaints() { - d->m_useSlowRepaints = true; + m_useSlowRepaints = true; setCanBlitOnScroll(false); } void FrameView::addSlowRepaintObject() { - if (!d->m_slowRepaintObjectCount) + if (!m_slowRepaintObjectCount) setCanBlitOnScroll(false); - d->m_slowRepaintObjectCount++; + m_slowRepaintObjectCount++; } void FrameView::removeSlowRepaintObject() { - ASSERT(d->m_slowRepaintObjectCount > 0); - d->m_slowRepaintObjectCount--; - if (!d->m_slowRepaintObjectCount) - setCanBlitOnScroll(!d->m_useSlowRepaints); + ASSERT(m_slowRepaintObjectCount > 0); + m_slowRepaintObjectCount--; + if (!m_slowRepaintObjectCount) + setCanBlitOnScroll(!useSlowRepaints()); +} + +void FrameView::setIsOverlapped(bool isOverlapped) +{ + if (isOverlapped == m_isOverlapped) + return; + + m_isOverlapped = isOverlapped; + setCanBlitOnScroll(!useSlowRepaints()); +} + +void FrameView::setContentIsOpaque(bool contentIsOpaque) +{ + if (contentIsOpaque == m_contentIsOpaque) + return; + + m_contentIsOpaque = contentIsOpaque; + setCanBlitOnScroll(!useSlowRepaints()); } void FrameView::restoreScrollbar() @@ -695,18 +723,20 @@ void FrameView::restoreScrollbar() void FrameView::scrollRectIntoViewRecursively(const IntRect& r) { - bool wasInProgrammaticScroll = d->m_inProgrammaticScroll; - d->m_inProgrammaticScroll = true; + bool wasInProgrammaticScroll = m_inProgrammaticScroll; + m_inProgrammaticScroll = true; + setLockedToAnchor(false); ScrollView::scrollRectIntoViewRecursively(r); - d->m_inProgrammaticScroll = wasInProgrammaticScroll; + m_inProgrammaticScroll = wasInProgrammaticScroll; } void FrameView::setScrollPosition(const IntPoint& scrollPoint) { - bool wasInProgrammaticScroll = d->m_inProgrammaticScroll; - d->m_inProgrammaticScroll = true; + bool wasInProgrammaticScroll = m_inProgrammaticScroll; + m_inProgrammaticScroll = true; + setLockedToAnchor(false); ScrollView::setScrollPosition(scrollPoint); - d->m_inProgrammaticScroll = wasInProgrammaticScroll; + m_inProgrammaticScroll = wasInProgrammaticScroll; } HostWindow* FrameView::hostWindow() const @@ -723,17 +753,27 @@ void FrameView::repaintContentRectangle(const IntRect& r, bool immediate) { ASSERT(!m_frame->document()->ownerElement()); - if (d->m_deferringRepaints && !immediate) { + double delay = adjustedDeferredRepaintDelay(); + if ((m_deferringRepaints || m_deferredRepaintTimer.isActive() || delay) && !immediate) { IntRect visibleContent = visibleContentRect(); visibleContent.intersect(r); - if (!visibleContent.isEmpty()) { - d->m_repaintCount++; - d->m_repaintRect.unite(r); - if (d->m_repaintCount == cRepaintRectUnionThreshold) - d->m_repaintRects.clear(); - else if (d->m_repaintCount < cRepaintRectUnionThreshold) - d->m_repaintRects.append(r); + 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; } @@ -749,10 +789,7 @@ void FrameView::beginDeferredRepaints() if (page->mainFrame() != m_frame) return page->mainFrame()->view()->beginDeferredRepaints(); - d->m_deferringRepaints++; - d->m_repaintCount = 0; - d->m_repaintRect = IntRect(); - d->m_repaintRects.clear(); + m_deferringRepaints++; } @@ -762,23 +799,94 @@ void FrameView::endDeferredRepaints() if (page->mainFrame() != m_frame) return page->mainFrame()->view()->endDeferredRepaints(); - ASSERT(d->m_deferringRepaints > 0); - if (--d->m_deferringRepaints == 0) { - if (d->m_repaintCount >= cRepaintRectUnionThreshold) - repaintContentRectangle(d->m_repaintRect, false); - else { - unsigned size = d->m_repaintRects.size(); - for (unsigned i = 0; i < size; i++) - repaintContentRectangle(d->m_repaintRects[i], false); - d->m_repaintRects.clear(); - } + ASSERT(m_deferringRepaints > 0); + + 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.stop(); + if (!m_deferringRepaints) + doDeferredRepaints(); + } +} + +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(); @@ -786,34 +894,34 @@ 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 (d->m_layoutRoot) { - d->m_layoutRoot->markContainingBlocksForLayout(false); - d->m_layoutRoot = 0; + if (m_layoutRoot) { + m_layoutRoot->markContainingBlocksForLayout(false); + m_layoutRoot = 0; } - if (!d->m_layoutSchedulingEnabled) + if (!m_layoutSchedulingEnabled) return; if (!needsLayout()) return; - if (!m_frame->document() || !m_frame->document()->shouldScheduleLayout()) + if (!m_frame->document()->shouldScheduleLayout()) return; int delay = m_frame->document()->minimumLayoutDelay(); - if (d->m_layoutTimer.isActive() && d->m_delayedLayout && !delay) + if (m_layoutTimer.isActive() && m_delayedLayout && !delay) unscheduleRelayout(); - if (d->m_layoutTimer.isActive()) + if (m_layoutTimer.isActive()) return; - d->m_delayedLayout = delay != 0; + m_delayedLayout = delay != 0; #ifdef INSTRUMENT_LAYOUT_SCHEDULING if (!m_frame->document()->ownerElement()) printf("Scheduling layout for %d\n", delay); #endif - d->m_layoutTimer.startOneShot(delay * 0.001); + m_layoutTimer.startOneShot(delay * 0.001); } static bool isObjectAncestorContainerOf(RenderObject* ancestor, RenderObject* descendant) @@ -829,7 +937,7 @@ void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot) { ASSERT(m_frame->view() == this); - if (!d->m_layoutSchedulingEnabled || (m_frame->contentRenderer() + if (!m_layoutSchedulingEnabled || (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())) { if (relayoutRoot) relayoutRoot->markContainingBlocksForLayout(false); @@ -837,33 +945,33 @@ void FrameView::scheduleRelayoutOfSubtree(RenderObject* relayoutRoot) } if (layoutPending()) { - if (d->m_layoutRoot != relayoutRoot) { - if (isObjectAncestorContainerOf(d->m_layoutRoot, relayoutRoot)) { + if (m_layoutRoot != relayoutRoot) { + if (isObjectAncestorContainerOf(m_layoutRoot, relayoutRoot)) { // Keep the current root - relayoutRoot->markContainingBlocksForLayout(false, d->m_layoutRoot); - } else if (d->m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, d->m_layoutRoot)) { + relayoutRoot->markContainingBlocksForLayout(false, m_layoutRoot); + } else if (m_layoutRoot && isObjectAncestorContainerOf(relayoutRoot, m_layoutRoot)) { // Re-root at relayoutRoot - d->m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot); - d->m_layoutRoot = relayoutRoot; + m_layoutRoot->markContainingBlocksForLayout(false, relayoutRoot); + m_layoutRoot = relayoutRoot; } else { // Just do a full relayout - if (d->m_layoutRoot) - d->m_layoutRoot->markContainingBlocksForLayout(false); - d->m_layoutRoot = 0; + if (m_layoutRoot) + m_layoutRoot->markContainingBlocksForLayout(false); + m_layoutRoot = 0; relayoutRoot->markContainingBlocksForLayout(false); } } } else { int delay = m_frame->document()->minimumLayoutDelay(); - d->m_layoutRoot = relayoutRoot; - d->m_delayedLayout = delay != 0; - d->m_layoutTimer.startOneShot(delay * 0.001); + m_layoutRoot = relayoutRoot; + m_delayedLayout = delay != 0; + m_layoutTimer.startOneShot(delay * 0.001); } } bool FrameView::layoutPending() const { - return d->m_layoutTimer.isActive(); + return m_layoutTimer.isActive(); } bool FrameView::needsLayout() const @@ -877,13 +985,18 @@ bool FrameView::needsLayout() const Document* document = m_frame->document(); return layoutPending() || (root && root->needsLayout()) - || d->m_layoutRoot - || (document && document->hasChangedChild()) // can occur when using WebKit ObjC interface - || m_frame->needsReapplyStyles(); + || m_layoutRoot + || (document && document->childNeedsStyleRecalc()) // can occur when using WebKit ObjC interface + || m_frame->needsReapplyStyles() + || (m_deferSetNeedsLayouts && m_setNeedsLayoutWasDeferred); } void FrameView::setNeedsLayout() { + if (m_deferSetNeedsLayouts) { + m_setNeedsLayoutWasDeferred = true; + return; + } RenderView* root = m_frame->contentRenderer(); if (root) root->setNeedsLayout(true); @@ -891,38 +1004,38 @@ void FrameView::setNeedsLayout() void FrameView::unscheduleRelayout() { - if (!d->m_layoutTimer.isActive()) + if (!m_layoutTimer.isActive()) 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 - d->m_layoutTimer.stop(); - d->m_delayedLayout = false; + m_layoutTimer.stop(); + m_delayedLayout = false; } bool FrameView::isTransparent() const { - return d->m_isTransparent; + return m_isTransparent; } void FrameView::setTransparent(bool isTransparent) { - d->m_isTransparent = isTransparent; + m_isTransparent = isTransparent; } Color FrameView::baseBackgroundColor() const { - return d->m_baseBackgroundColor; + return m_baseBackgroundColor; } void FrameView::setBaseBackgroundColor(Color bc) { if (!bc.isValid()) bc = Color::white; - d->m_baseBackgroundColor = bc; + m_baseBackgroundColor = bc; } void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool transparent) @@ -939,17 +1052,17 @@ void FrameView::updateBackgroundRecursively(const Color& backgroundColor, bool t bool FrameView::shouldUpdateWhileOffscreen() const { - return d->m_shouldUpdateWhileOffscreen; + return m_shouldUpdateWhileOffscreen; } void FrameView::setShouldUpdateWhileOffscreen(bool shouldUpdateWhileOffscreen) { - d->m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen; + m_shouldUpdateWhileOffscreen = shouldUpdateWhileOffscreen; } -void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<EventTargetNode> eventTarget) +void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<Node> eventTarget) { - if (!d->m_enqueueEvents) { + if (!m_enqueueEvents) { ExceptionCode ec = 0; eventTarget->dispatchEvent(event, ec); return; @@ -958,64 +1071,77 @@ void FrameView::scheduleEvent(PassRefPtr<Event> event, PassRefPtr<EventTargetNod ScheduledEvent* scheduledEvent = new ScheduledEvent; scheduledEvent->m_event = event; scheduledEvent->m_eventTarget = eventTarget; - d->m_scheduledEvents.append(scheduledEvent); + m_scheduledEvents.append(scheduledEvent); } void FrameView::pauseScheduledEvents() { - ASSERT(d->m_scheduledEvents.isEmpty() || d->m_enqueueEvents); - d->m_enqueueEvents++; + ASSERT(m_scheduledEvents.isEmpty() || m_enqueueEvents); + m_enqueueEvents++; } void FrameView::resumeScheduledEvents() { - d->m_enqueueEvents--; - if (!d->m_enqueueEvents) + m_enqueueEvents--; + if (!m_enqueueEvents) dispatchScheduledEvents(); - ASSERT(d->m_scheduledEvents.isEmpty() || d->m_enqueueEvents); + 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 (d->m_firstLayoutCallbackPending) { - d->m_firstLayoutCallbackPending = false; + if (m_firstLayoutCallbackPending) { + m_firstLayoutCallbackPending = false; m_frame->loader()->didFirstLayout(); } - if (d->m_isVisuallyNonEmpty && d->m_firstVisuallyNonEmptyLayoutCallbackPending) { - d->m_firstVisuallyNonEmptyLayoutCallbackPending = false; + if (m_isVisuallyNonEmpty && m_firstVisuallyNonEmptyLayoutCallbackPending) { + m_firstVisuallyNonEmptyLayoutCallbackPending = false; m_frame->loader()->didFirstVisuallyNonEmptyLayout(); } RenderView* root = m_frame->contentRenderer(); root->updateWidgetPositions(); - if (m_widgetUpdateSet && d->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()) { IntSize currentSize = IntSize(width(), height()); float currentZoomFactor = root->style()->zoom(); - bool resized = !d->m_firstLayout && (currentSize != d->m_lastLayoutSize || currentZoomFactor != d->m_lastZoomFactor); - d->m_lastLayoutSize = currentSize; - d->m_lastZoomFactor = currentZoomFactor; + bool resized = !m_firstLayout && (currentSize != m_lastLayoutSize || currentZoomFactor != m_lastZoomFactor); + m_lastLayoutSize = currentSize; + m_lastZoomFactor = currentZoomFactor; if (resized) - m_frame->sendResizeEvent(); + m_frame->eventHandler()->sendResizeEvent(); } } @@ -1026,37 +1152,37 @@ void FrameView::postLayoutTimerFired(Timer<FrameView>*) void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow) { - if (!d->m_viewportRenderer) + if (!m_viewportRenderer) return; - if (d->m_overflowStatusDirty) { - d->m_horizontalOverflow = horizontalOverflow; - d->m_verticalOverflow = verticalOverflow; - d->m_overflowStatusDirty = false; + if (m_overflowStatusDirty) { + m_horizontalOverflow = horizontalOverflow; + m_verticalOverflow = verticalOverflow; + m_overflowStatusDirty = false; return; } - bool horizontalOverflowChanged = (d->m_horizontalOverflow != horizontalOverflow); - bool verticalOverflowChanged = (d->m_verticalOverflow != verticalOverflow); + bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow); + bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow); if (horizontalOverflowChanged || verticalOverflowChanged) { - d->m_horizontalOverflow = horizontalOverflow; - d->m_verticalOverflow = verticalOverflow; + m_horizontalOverflow = horizontalOverflow; + m_verticalOverflow = verticalOverflow; scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow), - EventTargetNodeCast(d->m_viewportRenderer->element())); + m_viewportRenderer->node()); } } void FrameView::dispatchScheduledEvents() { - if (d->m_scheduledEvents.isEmpty()) + if (m_scheduledEvents.isEmpty()) return; - Vector<ScheduledEvent*> scheduledEventsCopy = d->m_scheduledEvents; - d->m_scheduledEvents.clear(); + Vector<ScheduledEvent*> scheduledEventsCopy = m_scheduledEvents; + m_scheduledEvents.clear(); Vector<ScheduledEvent*>::iterator end = scheduledEventsCopy.end(); for (Vector<ScheduledEvent*>::iterator it = scheduledEventsCopy.begin(); it != end; ++it) { @@ -1078,7 +1204,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. @@ -1120,7 +1246,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) @@ -1151,7 +1277,7 @@ void FrameView::updateDashboardRegions() if (!document->hasDashboardRegions()) return; Vector<DashboardRegionValue> newRegions; - document->renderer()->collectDashboardRegions(newRegions); + document->renderBox()->collectDashboardRegions(newRegions); if (newRegions == document->dashboardRegions()) return; document->setDashboardRegions(newRegions); @@ -1188,14 +1314,15 @@ void FrameView::updateControlTints() bool FrameView::wasScrolledByUser() const { - return d->m_wasScrolledByUser; + return m_wasScrolledByUser; } void FrameView::setWasScrolledByUser(bool wasScrolledByUser) { - if (d->m_inProgrammaticScroll) + if (m_inProgrammaticScroll) return; - d->m_wasScrolledByUser = wasScrolledByUser; + setLockedToAnchor(false); + m_wasScrolledByUser = wasScrolledByUser; } void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) @@ -1204,20 +1331,18 @@ 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. else if (isTransparent()) fillWithRed = false; // Transparent, don't fill with red. - else if (d->m_paintRestriction == PaintRestrictionSelectionOnly || d->m_paintRestriction == PaintRestrictionSelectionOnlyBlackText) + else if (m_paintRestriction == PaintRestrictionSelectionOnly || m_paintRestriction == PaintRestrictionSelectionOnlyBlackText) fillWithRed = false; // Selections are transparent, don't fill with red. - else if (d->m_nodeToDraw) + else if (m_nodeToDraw) fillWithRed = false; // Element images are transparent, don't fill with red. else fillWithRed = true; @@ -1237,17 +1362,21 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) } ASSERT(!needsLayout()); - ASSERT(!d->m_isPainting); + if (needsLayout()) + return; + + ASSERT(!m_isPainting); - d->m_isPainting = true; + m_isPainting = true; // m_nodeToDraw is used to draw only one element (and its descendants) - RenderObject* eltRenderer = d->m_nodeToDraw ? d->m_nodeToDraw->renderer() : 0; - if (d->m_paintRestriction == PaintRestrictionNone) + RenderObject* eltRenderer = m_nodeToDraw ? m_nodeToDraw->renderer() : 0; + if (m_paintRestriction == PaintRestrictionNone) document->invalidateRenderedRectsForMarkersInRect(rect); - contentRenderer->layer()->paint(p, rect, d->m_paintRestriction, eltRenderer); - - d->m_isPainting = false; + 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. @@ -1261,17 +1390,17 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) void FrameView::setPaintRestriction(PaintRestriction pr) { - d->m_paintRestriction = pr; + m_paintRestriction = pr; } bool FrameView::isPainting() const { - return d->m_isPainting; + return m_isPainting; } void FrameView::setNodeToDraw(Node* node) { - d->m_nodeToDraw = node; + m_nodeToDraw = node; } void FrameView::layoutIfNeededRecursive() @@ -1293,11 +1422,69 @@ void FrameView::layoutIfNeededRecursive() for (HashSet<Widget*>::const_iterator current = viewChildren->begin(); current != end; ++current) if ((*current)->isFrameView()) static_cast<FrameView*>(*current)->layoutIfNeededRecursive(); + + // layoutIfNeededRecursive is called when we need to make sure layout is up-to-date before + // painting, so we need to flush out any deferred repaints too. + if (m_deferredRepaintTimer.isActive()) { + m_deferredRepaintTimer.stop(); + doDeferredRepaints(); + } } -void FrameView::setIsVisuallyNonEmpty() +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*/) { - d->m_isVisuallyNonEmpty = true; + 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->overflowWidth(), (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/src/3rdparty/webkit/WebCore/page/FrameView.h b/src/3rdparty/webkit/WebCore/page/FrameView.h index 03de174..16eadc5 100644 --- a/src/3rdparty/webkit/WebCore/page/FrameView.h +++ b/src/3rdparty/webkit/WebCore/page/FrameView.h @@ -4,7 +4,7 @@ (C) 1998, 1999 Torben Weis (weis@kde.org) (C) 1999 Lars Knoll (knoll@kde.org) (C) 1999 Antti Koivisto (koivisto@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. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -35,25 +35,25 @@ namespace WebCore { class Color; class Event; -class EventTargetNode; class Frame; class FrameViewPrivate; class IntRect; -class PlatformMouseEvent; class Node; +class PlatformMouseEvent; class RenderLayer; class RenderObject; class RenderPartObject; +class ScheduledEvent; class String; template <typename T> class Timer; -class FrameView : public ScrollView { +class FrameView : public ScrollView, public RefCounted<FrameView> { public: friend class RenderView; - FrameView(Frame*); - FrameView(Frame*, const IntSize& initialSize); + static PassRefPtr<FrameView> create(Frame*); + static PassRefPtr<FrameView> create(Frame*, const IntSize& initialSize); virtual ~FrameView(); @@ -64,10 +64,6 @@ public: Frame* frame() const { return m_frame.get(); } void clearFrame(); - void ref() { ++m_refCount; } - void deref() { if (!--m_refCount) delete this; } - bool hasOneRef() { return m_refCount == 1; } - int marginWidth() const { return m_margins.width(); } // -1 means default int marginHeight() const { return m_margins.height(); } // -1 means default void setMarginWidth(int); @@ -88,13 +84,25 @@ public: bool layoutPending() const; RenderObject* layoutRoot(bool onlyDuringLayout = false) const; - int layoutCount() const; + int layoutCount() const { return m_layoutCount; } // These two helper functions just pass through to the RenderView. bool needsLayout() const; void setNeedsLayout(); - bool needsFullRepaint() const; + 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(); @@ -131,12 +139,16 @@ public: void setMediaType(const String&); void setUseSlowRepaints(); + void setIsOverlapped(bool); + void setContentIsOpaque(bool); void addSlowRepaintObject(); void removeSlowRepaintObject(); void beginDeferredRepaints(); void endDeferredRepaints(); + void checkStopDelayingDeferredRepaints(); + void resetDeferredRepaintDelay(); #if ENABLE(DASHBOARD_SUPPORT) void updateDashboardRegions(); @@ -145,7 +157,7 @@ public: void restoreScrollbar(); - void scheduleEvent(PassRefPtr<Event>, PassRefPtr<EventTargetNode>); + void scheduleEvent(PassRefPtr<Event>, PassRefPtr<Node>); void pauseScheduledEvents(); void resumeScheduledEvents(); void postLayoutTimerFired(Timer<FrameView>*); @@ -165,13 +177,26 @@ public: void layoutIfNeededRecursive(); - void setIsVisuallyNonEmpty(); + 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); + + bool lockedToAnchor() { return m_lockedToAnchor; } + void setLockedToAnchor(bool lockedToAnchor) { m_lockedToAnchor = lockedToAnchor; } + private: + FrameView(Frame*); + + void reset(); void init(); virtual bool isFrameView() const; + friend class RenderWidget; bool useSlowRepaints() const; void applyOverflowToViewport(RenderObject*, ScrollbarMode& hMode, ScrollbarMode& vMode); @@ -183,18 +208,90 @@ private: virtual void repaintContentRectangle(const IntRect&, bool immediate); virtual void contentsResized() { setNeedsLayout(); } - virtual void visibleContentsResized() { layout(); } - + virtual void visibleContentsResized() + { + if (needsLayout()) + 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; IntSize m_size; IntSize m_margins; OwnPtr<HashSet<RenderPartObject*> > m_widgetUpdateSet; RefPtr<Frame> m_frame; - FrameViewPrivate* d; + + bool m_doFullRepaint; + + ScrollbarMode m_vmode; + ScrollbarMode m_hmode; + bool m_useSlowRepaints; + bool m_isOverlapped; + bool m_contentIsOpaque; + unsigned m_slowRepaintObjectCount; + + int m_borderX, m_borderY; + + Timer<FrameView> m_layoutTimer; + bool m_delayedLayout; + RenderObject* m_layoutRoot; + + bool m_layoutSchedulingEnabled; + bool m_midLayout; + int m_layoutCount; + unsigned m_nestedLayoutCount; + Timer<FrameView> m_postLayoutTasksTimer; + bool m_firstLayoutCallbackPending; + + bool m_firstLayout; + bool m_needToInitScrollbars; + bool m_isTransparent; + Color m_baseBackgroundColor; + IntSize m_lastLayoutSize; + float m_lastZoomFactor; + + String m_mediaType; + + unsigned m_enqueueEvents; + Vector<ScheduledEvent*> m_scheduledEvents; + + bool m_overflowStatusDirty; + bool m_horizontalOverflow; + bool m_verticalOverflow; + RenderObject* m_viewportRenderer; + + bool m_wasScrolledByUser; + bool m_inProgrammaticScroll; + + unsigned m_deferringRepaints; + unsigned m_repaintCount; + Vector<IntRect> m_repaintRects; + Timer<FrameView> m_deferredRepaintTimer; + double m_deferredRepaintDelay; + double m_lastPaintTime; + + bool m_shouldUpdateWhileOffscreen; + + unsigned m_deferSetNeedsLayouts; + bool m_setNeedsLayoutWasDeferred; + + RefPtr<Node> m_nodeToDraw; + PaintRestriction m_paintRestriction; + bool m_isPainting; + + bool m_isVisuallyNonEmpty; + bool m_firstVisuallyNonEmptyLayoutCallbackPending; + + bool m_lockedToAnchor; }; -} +} // namespace WebCore -#endif +#endif // FrameView_h diff --git a/src/3rdparty/webkit/WebCore/page/Geolocation.cpp b/src/3rdparty/webkit/WebCore/page/Geolocation.cpp index f82e95d..8abe8a6 100644 --- a/src/3rdparty/webkit/WebCore/page/Geolocation.cpp +++ b/src/3rdparty/webkit/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,19 +26,26 @@ #include "config.h" #include "Geolocation.h" +#include "Chrome.h" #include "Document.h" #include "Frame.h" +#include "Page.h" #include "PositionError.h" namespace WebCore { -Geolocation::GeoNotifier::GeoNotifier(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PositionOptions* options) +Geolocation::GeoNotifier::GeoNotifier(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) : m_successCallback(successCallback) , m_errorCallback(errorCallback) + , m_options(options) , m_timer(this, &Geolocation::GeoNotifier::timerFired) { - if (m_errorCallback && options) - m_timer.startOneShot(options->timeout() / 1000.0); +} + +void Geolocation::GeoNotifier::startTimer() +{ + if (m_errorCallback && m_options) + m_timer.startOneShot(m_options->timeout() / 1000.0); } void Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*) @@ -54,7 +61,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,16 +73,14 @@ Geolocation::Geolocation(Frame* frame) void Geolocation::disconnectFrame() { m_service->stopUpdating(); - if (m_frame->document()) - m_frame->document()->setUsingGeolocation(false); m_frame = 0; } -void Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PositionOptions* options) +void Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) { RefPtr<GeoNotifier> notifier = GeoNotifier::create(successCallback, errorCallback, options); - if (!m_service->startUpdating(options)) { + if (!m_service->startUpdating(notifier->m_options.get())) { if (notifier->m_errorCallback) { RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, "Unable to Start"); notifier->m_errorCallback->handleEvent(error.get()); @@ -82,11 +91,11 @@ void Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallbac m_oneShots.add(notifier); } -int Geolocation::watchPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PositionOptions* options) +int Geolocation::watchPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options) { RefPtr<GeoNotifier> notifier = GeoNotifier::create(successCallback, errorCallback, options); - if (!m_service->startUpdating(options)) { + if (!m_service->startUpdating(notifier->m_options.get())) { if (notifier->m_errorCallback) { RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, "Unable to Start"); notifier->m_errorCallback->handleEvent(error.get()); @@ -121,6 +130,19 @@ void Geolocation::resume() m_service->resume(); } +void Geolocation::setIsAllowed(bool allowed) +{ + m_allowGeolocation = allowed ? Yes : No; + + if (isAllowed()) { + startTimers(); + 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; @@ -189,6 +211,37 @@ void Geolocation::sendPositionToWatchers(Geoposition* position) } } +void Geolocation::startTimer(Vector<RefPtr<GeoNotifier> >& notifiers) +{ + Vector<RefPtr<GeoNotifier> >::const_iterator end = notifiers.end(); + for (Vector<RefPtr<GeoNotifier> >::const_iterator it = notifiers.begin(); it != end; ++it) { + RefPtr<GeoNotifier> notifier = *it; + notifier->startTimer(); + } +} + +void Geolocation::startTimersForOneShots() +{ + Vector<RefPtr<GeoNotifier> > copy; + copyToVector(m_oneShots, copy); + + startTimer(copy); +} + +void Geolocation::startTimersForWatchers() +{ + Vector<RefPtr<GeoNotifier> > copy; + copyValuesToVector(m_watchers, copy); + + startTimer(copy); +} + +void Geolocation::startTimers() +{ + startTimersForOneShots(); + startTimersForWatchers(); +} + void Geolocation::handleError(PositionError* error) { ASSERT(error); @@ -199,10 +252,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/src/3rdparty/webkit/WebCore/page/Geolocation.h b/src/3rdparty/webkit/WebCore/page/Geolocation.h index 572cbd8..ae24bdd 100644 --- a/src/3rdparty/webkit/WebCore/page/Geolocation.h +++ b/src/3rdparty/webkit/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 @@ -38,6 +38,7 @@ #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> +#include <wtf/Vector.h> namespace WebCore { @@ -54,30 +55,38 @@ public: Geoposition* lastPosition() const { return m_service->lastPosition(); } - void getCurrentPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PositionOptions*); - int watchPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PositionOptions*); + void getCurrentPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); + int watchPosition(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); void clearWatch(int watchId); 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*); class GeoNotifier : public RefCounted<GeoNotifier> { public: - static PassRefPtr<GeoNotifier> create(PassRefPtr<PositionCallback> positionCallback, PassRefPtr<PositionErrorCallback> positionErrorCallback, PositionOptions* options) { return adoptRef(new GeoNotifier(positionCallback, positionErrorCallback, options)); } + static PassRefPtr<GeoNotifier> create(PassRefPtr<PositionCallback> positionCallback, PassRefPtr<PositionErrorCallback> positionErrorCallback, PassRefPtr<PositionOptions> options) { return adoptRef(new GeoNotifier(positionCallback, positionErrorCallback, options)); } + void startTimer(); void timerFired(Timer<GeoNotifier>*); RefPtr<PositionCallback> m_successCallback; RefPtr<PositionErrorCallback> m_errorCallback; + RefPtr<PositionOptions> m_options; Timer<GeoNotifier> m_timer; private: - GeoNotifier(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PositionOptions*); + GeoNotifier(PassRefPtr<PositionCallback>, PassRefPtr<PositionErrorCallback>, PassRefPtr<PositionOptions>); }; - + bool hasListeners() const { return !m_oneShots.isEmpty() || !m_watchers.isEmpty(); } void sendErrorToOneShots(PositionError*); @@ -85,11 +94,19 @@ private: void sendPositionToOneShots(Geoposition*); void sendPositionToWatchers(Geoposition*); - void handleError(PositionError*); + static void startTimer(Vector<RefPtr<GeoNotifier> >&); + void startTimersForOneShots(); + void startTimersForWatchers(); + void startTimers(); + 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 +114,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/src/3rdparty/webkit/WebCore/page/Geoposition.cpp b/src/3rdparty/webkit/WebCore/page/Geoposition.cpp index 1792a1f..8f7a5c8 100644 --- a/src/3rdparty/webkit/WebCore/page/Geoposition.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/page/Geoposition.h b/src/3rdparty/webkit/WebCore/page/Geoposition.h index 9ce50e5..505e8b3 100644 --- a/src/3rdparty/webkit/WebCore/page/Geoposition.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/page/Geoposition.idl b/src/3rdparty/webkit/WebCore/page/Geoposition.idl index 554bb30..de508fe 100644 --- a/src/3rdparty/webkit/WebCore/page/Geoposition.idl +++ b/src/3rdparty/webkit/WebCore/page/Geoposition.idl @@ -26,16 +26,10 @@ 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) +#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT [DontEnum] DOMString toString(); #endif }; diff --git a/src/3rdparty/webkit/WebCore/page/History.idl b/src/3rdparty/webkit/WebCore/page/History.idl index e86cf92..fa308fb 100644 --- a/src/3rdparty/webkit/WebCore/page/History.idl +++ b/src/3rdparty/webkit/WebCore/page/History.idl @@ -26,6 +26,9 @@ module window { interface [ +#if defined(V8_BINDING) && 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/src/3rdparty/webkit/WebCore/page/Location.cpp b/src/3rdparty/webkit/WebCore/page/Location.cpp index 454aa78..c8780eb 100644 --- a/src/3rdparty/webkit/WebCore/page/Location.cpp +++ b/src/3rdparty/webkit/WebCore/page/Location.cpp @@ -49,7 +49,12 @@ void Location::disconnectFrame() inline const KURL& Location::url() const { ASSERT(m_frame); - return m_frame->loader()->url(); + + const KURL& url = m_frame->loader()->url(); + if (!url.isValid()) + return blankURL(); // Use "about:blank" while the page is still loading (before we have a frame). + + return url; } String Location::href() const @@ -111,7 +116,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 +126,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/src/3rdparty/webkit/WebCore/page/Location.idl b/src/3rdparty/webkit/WebCore/page/Location.idl index 91822ab..e7fa31a 100644 --- a/src/3rdparty/webkit/WebCore/page/Location.idl +++ b/src/3rdparty/webkit/WebCore/page/Location.idl @@ -29,16 +29,22 @@ module window { interface [ +#if defined(V8_BINDING) && V8_BINDING + CheckDomainSecurity, +#endif CustomGetOwnPropertySlot, CustomPutFunction, CustomDeleteProperty, - CustomGetPropertyNames + CustomGetPropertyNames, + CustomDefineGetter, + CustomPrototypePutFunction, + CustomPrototypeDefineGetter ] 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; @@ -49,8 +55,11 @@ module window { attribute [CustomSetter] DOMString search; attribute [CustomSetter] DOMString hash; -#if defined(LANGUAGE_JAVASCRIPT) - [DontEnum, Custom] DOMString toString(); +#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT + [DontEnum, Custom, V8OnInstance, V8ReadOnly] DOMString toString(); +#endif +#if defined(V8_BINDING) && V8_BINDING + [DontEnum, Custom, V8OnInstance, V8ReadOnly] DOMObject valueOf(); #endif }; diff --git a/src/3rdparty/webkit/WebCore/page/Navigator.cpp b/src/3rdparty/webkit/WebCore/page/Navigator.cpp index 429ec00..3603b86 100644 --- a/src/3rdparty/webkit/WebCore/page/Navigator.cpp +++ b/src/3rdparty/webkit/WebCore/page/Navigator.cpp @@ -75,7 +75,7 @@ static bool shouldHideFourDot(Frame* frame) const String* sourceURL = frame->script()->sourceURL(); if (!sourceURL) return false; - if (!(sourceURL->endsWith("/dqm_script.js") || sourceURL->endsWith("/dqm_loader.js"))) + if (!(sourceURL->endsWith("/dqm_script.js") || sourceURL->endsWith("/dqm_loader.js") || sourceURL->endsWith("/tdqm_loader.js"))) return false; Settings* settings = frame->settings(); if (!settings) @@ -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/src/3rdparty/webkit/WebCore/page/Navigator.idl b/src/3rdparty/webkit/WebCore/page/Navigator.idl index 905159c..8048ff3 100644 --- a/src/3rdparty/webkit/WebCore/page/Navigator.idl +++ b/src/3rdparty/webkit/WebCore/page/Navigator.idl @@ -24,7 +24,7 @@ module window { ] Navigator { readonly attribute DOMString appCodeName; readonly attribute DOMString appName; - readonly attribute [CustomGetter] DOMString appVersion; + readonly attribute DOMString appVersion; readonly attribute DOMString language; readonly attribute DOMString userAgent; readonly attribute DOMString platform; @@ -38,7 +38,8 @@ module window { boolean javaEnabled(); readonly attribute boolean onLine; -#if ENABLE_GEOLOCATION + +#if defined(ENABLE_GEOLOCATION) && ENABLE_GEOLOCATION readonly attribute Geolocation geolocation; #endif }; diff --git a/src/3rdparty/webkit/WebCore/page/NavigatorBase.cpp b/src/3rdparty/webkit/WebCore/page/NavigatorBase.cpp index 27c9fdd..5138b0f 100644 --- a/src/3rdparty/webkit/WebCore/page/NavigatorBase.cpp +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/page/Page.cpp b/src/3rdparty/webkit/WebCore/page/Page.cpp index 460183a..70b4459 100644 --- a/src/3rdparty/webkit/WebCore/page/Page.cpp +++ b/src/3rdparty/webkit/WebCore/page/Page.cpp @@ -21,14 +21,14 @@ #include "config.h" #include "Page.h" +#include "CSSStyleSelector.h" #include "Chrome.h" #include "ChromeClient.h" #include "ContextMenuClient.h" #include "ContextMenuController.h" -#include "CSSStyleSelector.h" -#include "EditorClient.h" #include "DOMWindow.h" #include "DragController.h" +#include "EditorClient.h" #include "EventNames.h" #include "FileSystem.h" #include "FocusController.h" @@ -36,21 +36,22 @@ #include "FrameLoader.h" #include "FrameTree.h" #include "FrameView.h" +#include "HTMLElement.h" #include "HistoryItem.h" #include "InspectorController.h" #include "Logging.h" -#include "NetworkStateNotifier.h" #include "Navigator.h" +#include "NetworkStateNotifier.h" #include "PageGroup.h" #include "PluginData.h" #include "ProgressTracker.h" #include "RenderWidget.h" +#include "ScriptController.h" #include "SelectionController.h" #include "Settings.h" #include "StringHash.h" #include "TextResourceDecoder.h" #include "Widget.h" -#include "ScriptController.h" #include <wtf/HashMap.h> #include <wtf/RefCountedLeakCounter.h> #include <wtf/StdLibExtras.h> @@ -89,20 +90,8 @@ static void networkStateChanged() } AtomicString eventName = networkStateNotifier().onLine() ? eventNames().onlineEvent : eventNames().offlineEvent; - - 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(); - if (!eventTarget) - eventTarget = document; - - eventTarget->dispatchEventForType(eventName, false, false); - } + for (unsigned i = 0; i < frames.size(); i++) + frames[i]->document()->dispatchWindowEvent(eventName, false, false); } Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, EditorClient* editorClient, DragClient* dragClient, InspectorClient* inspectorClient) @@ -111,7 +100,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)) @@ -123,13 +112,12 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi , m_cookieEnabled(true) , m_areMemoryCacheClientCallsEnabled(true) , m_mediaVolume(1) + , m_javaScriptURLsAreAllowed(true) , m_parentInspectorController(0) , m_didLoadUserStyleSheet(false) , m_userStyleSheetModificationTime(0) , m_group(0) , m_debugger(0) - , m_pendingUnloadEventCount(0) - , m_pendingBeforeUnloadEventCount(0) , m_customHTMLTokenizerTimeDelay(-1) , m_customHTMLTokenizerChunkSize(-1) { @@ -157,11 +145,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(); @@ -215,7 +201,19 @@ bool Page::goForward() void Page::goToItem(HistoryItem* item, FrameLoadType type) { // Abort any current load if we're going to a history item - m_mainFrame->loader()->stopAllLoaders(); + + // Define what to do with any open database connections. By default we stop them and terminate the database thread. + DatabasePolicy databasePolicy = DatabasePolicyStop; + +#if ENABLE(DATABASE) + // If we're navigating the history via a fragment on the same document, then we do not want to stop databases. + const KURL& currentURL = m_mainFrame->loader()->url(); + const KURL& newURL = item->url(); + + if (newURL.hasRef() && equalIgnoringRef(currentURL, newURL)) + databasePolicy = DatabasePolicyContinue; +#endif + m_mainFrame->loader()->stopAllLoaders(databasePolicy); m_mainFrame->loader()->goToItem(item, type); } @@ -233,7 +231,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 +356,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 +401,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 +473,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; } @@ -548,46 +562,6 @@ void Page::setSessionStorage(PassRefPtr<SessionStorage> newStorage) m_sessionStorage = newStorage; } #endif - -unsigned Page::pendingUnloadEventCount() -{ - return m_pendingUnloadEventCount; -} - -void Page::changePendingUnloadEventCount(int delta) -{ - if (!delta) - return; - ASSERT( (delta + (int)m_pendingUnloadEventCount) >= 0 ); - - if (m_pendingUnloadEventCount == 0) - m_chrome->disableSuddenTermination(); - else if ((m_pendingUnloadEventCount + delta) == 0) - m_chrome->enableSuddenTermination(); - - m_pendingUnloadEventCount += delta; - return; -} - -unsigned Page::pendingBeforeUnloadEventCount() -{ - return m_pendingBeforeUnloadEventCount; -} - -void Page::changePendingBeforeUnloadEventCount(int delta) -{ - if (!delta) - return; - ASSERT( (delta + (int)m_pendingBeforeUnloadEventCount) >= 0 ); - - if (m_pendingBeforeUnloadEventCount == 0) - m_chrome->disableSuddenTermination(); - else if ((m_pendingBeforeUnloadEventCount + delta) == 0) - m_chrome->enableSuddenTermination(); - - m_pendingBeforeUnloadEventCount += delta; - return; -} #if ENABLE(WML) WMLPageState* Page::wmlPageState() @@ -629,4 +603,14 @@ void Page::setMemoryCacheClientCallsEnabled(bool enabled) frame->loader()->tellClientAboutPastMemoryCacheLoads(); } +void Page::setJavaScriptURLsAreAllowed(bool areAllowed) +{ + m_javaScriptURLsAreAllowed = areAllowed; +} + +bool Page::javaScriptURLsAreAllowed() const +{ + return m_javaScriptURLsAreAllowed; +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Page.h b/src/3rdparty/webkit/WebCore/page/Page.h index de2b3f6..eedd24c 100644 --- a/src/3rdparty/webkit/WebCore/page/Page.h +++ b/src/3rdparty/webkit/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; @@ -70,7 +70,6 @@ namespace WebCore { class WMLPageState; #endif - enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive }; enum FindDirection { FindDirectionForward, FindDirectionBackward }; class Page : Noncopyable { @@ -138,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; } @@ -154,13 +153,12 @@ 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; - - void changePendingUnloadEventCount(int delta); - unsigned pendingUnloadEventCount(); - void changePendingBeforeUnloadEventCount(int delta); - unsigned pendingBeforeUnloadEventCount(); static void setDebuggerForAllPages(JSC::Debugger*); void setDebugger(JSC::Debugger*); @@ -197,6 +195,9 @@ namespace WebCore { void setMemoryCacheClientCallsEnabled(bool); bool areMemoryCacheClientCallsEnabled() const { return m_areMemoryCacheClientCallsEnabled; } + void setJavaScriptURLsAreAllowed(bool); + bool javaScriptURLsAreAllowed() const; + private: void initGroup(); @@ -205,7 +206,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; @@ -228,7 +229,9 @@ namespace WebCore { bool m_cookieEnabled; bool m_areMemoryCacheClientCallsEnabled; float m_mediaVolume; - + + bool m_javaScriptURLsAreAllowed; + InspectorController* m_parentInspectorController; String m_userStyleSheetPath; @@ -240,9 +243,6 @@ namespace WebCore { PageGroup* m_group; JSC::Debugger* m_debugger; - - unsigned m_pendingUnloadEventCount; - unsigned m_pendingBeforeUnloadEventCount; double m_customHTMLTokenizerTimeDelay; int m_customHTMLTokenizerChunkSize; diff --git a/src/3rdparty/webkit/WebCore/page/PageGroupLoadDeferrer.cpp b/src/3rdparty/webkit/WebCore/page/PageGroupLoadDeferrer.cpp new file mode 100644 index 0000000..f274de3 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/PageGroupLoadDeferrer.cpp @@ -0,0 +1,72 @@ +/* + * 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 + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "PageGroupLoadDeferrer.h" + +#include "Frame.h" +#include "Page.h" +#include "PageGroup.h" +#include <wtf/HashSet.h> + +namespace WebCore { + +using namespace std; + +PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf) +{ + const HashSet<Page*>& pages = page->group().pages(); + + HashSet<Page*>::const_iterator end = pages.end(); + for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it) { + Page* otherPage = *it; + if ((deferSelf || otherPage != page)) { + if (!otherPage->defersLoading()) + m_deferredFrames.append(otherPage->mainFrame()); + +#if !PLATFORM(MAC) + for (Frame* frame = otherPage->mainFrame(); frame; frame = frame->tree()->traverseNext()) + frame->document()->suspendActiveDOMObjects(); +#endif + } + } + + size_t count = m_deferredFrames.size(); + for (size_t i = 0; i < count; ++i) + if (Page* page = m_deferredFrames[i]->page()) + page->setDefersLoading(true); +} + +PageGroupLoadDeferrer::~PageGroupLoadDeferrer() +{ + for (size_t i = 0; i < m_deferredFrames.size(); ++i) { + if (Page* page = m_deferredFrames[i]->page()) { + page->setDefersLoading(false); + +#if !PLATFORM(MAC) + for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) + frame->document()->resumeActiveDOMObjects(); +#endif + } + } +} + + +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/qt/AccessibilityObjectQt.cpp b/src/3rdparty/webkit/WebCore/page/PageGroupLoadDeferrer.h index 1710027..1bdb45c 100644 --- a/src/3rdparty/webkit/WebCore/page/qt/AccessibilityObjectQt.cpp +++ b/src/3rdparty/webkit/WebCore/page/PageGroupLoadDeferrer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Ltd. + * 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 @@ -17,18 +17,25 @@ * Boston, MA 02110-1301, USA. */ -#include "config.h" -#include "AccessibilityObject.h" +#ifndef PageGroupLoadDeferrer_h +#define PageGroupLoadDeferrer_h -#if HAVE(ACCESSIBILITY) +#include <wtf/RefPtr.h> +#include <wtf/Vector.h> namespace WebCore { -bool AccessibilityObject::accessibilityIgnoreAttachment() const -{ - return false; -} + class Frame; + class Page; + + class PageGroupLoadDeferrer : Noncopyable { + public: + PageGroupLoadDeferrer(Page*, bool deferSelf); + ~PageGroupLoadDeferrer(); -} // namespace WebCore + private: + Vector<RefPtr<Frame>, 16> m_deferredFrames; + }; +} -#endif // HAVE(ACCESSIBILITY) +#endif // PageGroupLoadDeferrer_h diff --git a/src/3rdparty/webkit/WebCore/page/PositionOptions.h b/src/3rdparty/webkit/WebCore/page/PositionOptions.h index dc9c167..10845d3 100644 --- a/src/3rdparty/webkit/WebCore/page/PositionOptions.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/page/PrintContext.cpp b/src/3rdparty/webkit/WebCore/page/PrintContext.cpp index 79672a3..2202559 100644 --- a/src/3rdparty/webkit/WebCore/page/PrintContext.cpp +++ b/src/3rdparty/webkit/WebCore/page/PrintContext.cpp @@ -67,7 +67,7 @@ void PrintContext::computePageRects(const FloatRect& printRect, float headerHeig float ratio = printRect.height() / printRect.width(); - float pageWidth = (float)root->docWidth(); + float pageWidth = (float)root->overflowWidth(); float pageHeight = pageWidth * ratio; outPageHeight = pageHeight; // this is the height of the page adjusted by margins pageHeight -= headerHeight + footerHeight; @@ -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/src/3rdparty/webkit/WebCore/page/Screen.cpp b/src/3rdparty/webkit/WebCore/page/Screen.cpp index 396a6f4..d2bb60f 100644 --- a/src/3rdparty/webkit/WebCore/page/Screen.cpp +++ b/src/3rdparty/webkit/WebCore/page/Screen.cpp @@ -43,6 +43,11 @@ Screen::Screen(Frame* frame) { } +Frame* Screen::frame() const +{ + return m_frame; +} + void Screen::disconnectFrame() { m_frame = 0; diff --git a/src/3rdparty/webkit/WebCore/page/Screen.h b/src/3rdparty/webkit/WebCore/page/Screen.h index 288b1ac..2c84abd 100644 --- a/src/3rdparty/webkit/WebCore/page/Screen.h +++ b/src/3rdparty/webkit/WebCore/page/Screen.h @@ -40,6 +40,8 @@ namespace WebCore { class Screen : public RefCounted<Screen> { public: static PassRefPtr<Screen> create(Frame *frame) { return adoptRef(new Screen(frame)); } + + Frame* frame() const; void disconnectFrame(); unsigned height() const; diff --git a/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp b/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp index 792c3bb..187ec31 100644 --- a/src/3rdparty/webkit/WebCore/page/SecurityOrigin.cpp +++ b/src/3rdparty/webkit/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) { @@ -96,6 +98,8 @@ bool SecurityOrigin::isEmpty() const PassRefPtr<SecurityOrigin> SecurityOrigin::create(const KURL& url) { + if (!url.isValid()) + return adoptRef(new SecurityOrigin(KURL())); return adoptRef(new SecurityOrigin(url)); } @@ -117,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) @@ -158,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) @@ -182,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 @@ -209,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); @@ -224,7 +233,7 @@ String SecurityOrigin::toString() const PassRefPtr<SecurityOrigin> SecurityOrigin::createFromString(const String& originString) { - return SecurityOrigin::create(KURL(originString)); + return SecurityOrigin::create(KURL(KURL(), originString)); } static const char SeparatorCharacter = '_'; @@ -237,12 +246,13 @@ PassRefPtr<SecurityOrigin> SecurityOrigin::createFromDatabaseIdentifier(const St return create(KURL()); // Make sure there's a second separator - int separator2 = databaseIdentifier.find(SeparatorCharacter, separator1 + 1); + int separator2 = databaseIdentifier.reverseFind(SeparatorCharacter); if (separator2 == -1) return create(KURL()); - // Make sure there's not a third separator - if (databaseIdentifier.reverseFind(SeparatorCharacter) != separator2) + // Ensure there were at least 2 seperator characters. Some hostnames on intranets have + // underscores in them, so we'll assume that any additional underscores are part of the host. + if (separator1 != separator2) return create(KURL()); // Make sure the port section is a valid port number or doesn't exist @@ -257,7 +267,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 @@ -268,6 +278,9 @@ String SecurityOrigin::databaseIdentifier() const bool SecurityOrigin::equal(const SecurityOrigin* other) const { + if (other == this) + return true; + if (!isSameSchemeHostPort(other)) return false; diff --git a/src/3rdparty/webkit/WebCore/page/SecurityOrigin.h b/src/3rdparty/webkit/WebCore/page/SecurityOrigin.h index 1f2624e..96f85df 100644 --- a/src/3rdparty/webkit/WebCore/page/SecurityOrigin.h +++ b/src/3rdparty/webkit/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/src/3rdparty/webkit/WebCore/page/Settings.cpp b/src/3rdparty/webkit/WebCore/page/Settings.cpp index 9e4b7b5..91ec0b3 100644 --- a/src/3rdparty/webkit/WebCore/page/Settings.cpp +++ b/src/3rdparty/webkit/WebCore/page/Settings.cpp @@ -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. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,6 +33,8 @@ #include "PageCache.h" #include <limits> +using namespace std; + namespace WebCore { static void setNeedsReapplyStylesInAllFrames(Page* page) @@ -53,13 +55,17 @@ Settings::Settings(Page* page) , m_minimumLogicalFontSize(0) , m_defaultFontSize(0) , m_defaultFixedFontSize(0) + , m_maximumDecodedImageSize(numeric_limits<size_t>::max()) , m_isJavaEnabled(false) , m_loadsImagesAutomatically(false) , m_privateBrowsingEnabled(false) + , m_caretBrowsingEnabled(false) , m_arePluginsEnabled(false) , m_databasesEnabled(false) , m_localStorageEnabled(false) , m_isJavaScriptEnabled(false) + , m_isWebSecurityEnabled(true) + , m_allowUniversalAccessFromFileURLs(true) , m_javaScriptCanOpenWindowsAutomatically(false) , m_shouldPrintBackgrounds(false) , m_textAreasAreResizable(false) @@ -68,6 +74,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) @@ -80,11 +88,21 @@ 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_maximumDecodedImageSize(std::numeric_limits<size_t>::max()) + , m_usesEncodingDetector(false) + , m_allowScriptsToCloseWindows(false) + , m_editingBehavior( +#if PLATFORM(MAC) + EditingMacBehavior +#else + EditingWindowsBehavior +#endif + ) + // FIXME: This should really be disabled by default as it makes platforms that don't support the feature download files + // they can't use by. Leaving enabled for now to not change existing behavior. + , m_downloadableBinaryFontsEnabled(true) { // A Frame may not have been created yet, so we initialize the AtomicString // hash before trying to use it. @@ -191,6 +209,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; @@ -283,6 +311,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; @@ -364,11 +402,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; @@ -405,4 +438,24 @@ void Settings::setShouldPaintNativeControls(bool shouldPaintNativeControls) } #endif +void Settings::setUsesEncodingDetector(bool usesEncodingDetector) +{ + m_usesEncodingDetector = usesEncodingDetector; +} + +void Settings::setAllowScriptsToCloseWindows(bool allowScriptsToCloseWindows) +{ + m_allowScriptsToCloseWindows = allowScriptsToCloseWindows; +} + +void Settings::setCaretBrowsingEnabled(bool caretBrowsingEnabled) +{ + m_caretBrowsingEnabled = caretBrowsingEnabled; +} + +void Settings::setDownloadableBinaryFontsEnabled(bool downloadableBinaryFontsEnabled) +{ + m_downloadableBinaryFontsEnabled = downloadableBinaryFontsEnabled; +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/Settings.h b/src/3rdparty/webkit/WebCore/page/Settings.h index d46a3c6..62cf7f6 100644 --- a/src/3rdparty/webkit/WebCore/page/Settings.h +++ b/src/3rdparty/webkit/WebCore/page/Settings.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * (C) 2006 Graham Dennis (graham.dennis@gmail.com) * * Redistribution and use in source and binary forms, with or without @@ -28,7 +28,7 @@ #define Settings_h #include "AtomicString.h" -#include "FontDescription.h" +#include "FontRenderingMode.h" #include "KURL.h" namespace WebCore { @@ -36,7 +36,7 @@ namespace WebCore { class Page; enum EditableLinkBehavior { - EditableLinkDefaultBehavior = 0, + EditableLinkDefaultBehavior, EditableLinkAlwaysLive, EditableLinkOnlyLiveWithShiftKey, EditableLinkLiveWhenNotFocused, @@ -49,6 +49,21 @@ namespace WebCore { TextDirectionSubmenuAlwaysIncluded }; + // There are multiple editing details that are different on Windows than Macintosh. + // We use a single switch for all of them. Some examples: + // + // 1) Clicking below the last line of an editable area puts the caret at the end + // of the last line on Mac, but in the middle of the last line on Windows. + // 2) Pushing the down arrow key on the last line puts the caret at the end of the + // last line on Mac, but does nothing on Windows. A similar case exists on the + // top line. + // + // This setting is intended to control these sorts of behaviors. There are some other + // behaviors with individual function calls on EditorClient (smart copy and paste and + // selecting the space after a double click) that could be combined with this if + // if possible in the future. + enum EditingBehavior { EditingMacBehavior, EditingWindowsBehavior }; + class Settings { public: Settings(Page*); @@ -89,8 +104,14 @@ 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; } + bool javaScriptCanOpenWindowsAutomatically() const { return m_javaScriptCanOpenWindowsAutomatically; } void setJavaEnabled(bool); bool isJavaEnabled() const { return m_isJavaEnabled; } @@ -106,9 +127,15 @@ namespace WebCore { void setPrivateBrowsingEnabled(bool); bool privateBrowsingEnabled() const { return m_privateBrowsingEnabled; } - + + void setCaretBrowsingEnabled(bool); + bool caretBrowsingEnabled() const { return m_caretBrowsingEnabled; } + 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; } @@ -136,6 +163,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; } @@ -172,9 +205,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; } @@ -199,6 +229,15 @@ namespace WebCore { static bool shouldPaintNativeControls() { return gShouldPaintNativeControls; } #endif + void setAllowScriptsToCloseWindows(bool); + bool allowScriptsToCloseWindows() const { return m_allowScriptsToCloseWindows; } + + void setEditingBehavior(EditingBehavior behavior) { m_editingBehavior = behavior; } + EditingBehavior editingBehavior() const { return static_cast<EditingBehavior>(m_editingBehavior); } + + void setDownloadableBinaryFontsEnabled(bool); + bool downloadableBinaryFontsEnabled() const { return m_downloadableBinaryFontsEnabled; } + private: Page* m_page; @@ -218,13 +257,17 @@ namespace WebCore { int m_minimumLogicalFontSize; int m_defaultFontSize; int m_defaultFixedFontSize; + size_t m_maximumDecodedImageSize; bool m_isJavaEnabled : 1; bool m_loadsImagesAutomatically : 1; bool m_privateBrowsingEnabled : 1; + bool m_caretBrowsingEnabled : 1; bool m_arePluginsEnabled : 1; 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; @@ -233,6 +276,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; @@ -245,11 +290,13 @@ 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; - size_t m_maximumDecodedImageSize; + bool m_usesEncodingDetector : 1; + bool m_allowScriptsToCloseWindows : 1; + unsigned m_editingBehavior : 1; + bool m_downloadableBinaryFontsEnabled : 1; #if USE(SAFARI_THEME) static bool gShouldPaintNativeControls; diff --git a/src/3rdparty/webkit/WebCore/page/win/AccessibilityObjectWrapperWin.h b/src/3rdparty/webkit/WebCore/page/WebKitPoint.h index 779443c..501b17f 100644 --- a/src/3rdparty/webkit/WebCore/page/win/AccessibilityObjectWrapperWin.h +++ b/src/3rdparty/webkit/WebCore/page/WebKitPoint.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * 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 @@ -10,10 +10,10 @@ * 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 + * 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 INC. OR + * 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 @@ -23,32 +23,41 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef WebKitPoint_h +#define WebKitPoint_h -#ifndef AccessibilityObjectWrapperWin_h -#define AccessibilityObjectWrapperWin_h +#include <wtf/RefCounted.h> namespace WebCore { - class AccessibilityObject; - - class AccessibilityObjectWrapper : public IUnknown { + class WebKitPoint : public RefCounted<WebKitPoint> { public: - // IUnknown - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) = 0; - virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; - virtual ULONG STDMETHODCALLTYPE Release(void) = 0; - virtual void detach() = 0; - bool attached() const { return m_object; } - AccessibilityObject* accessibilityObject() const { return m_object; } - - protected: - AccessibilityObjectWrapper(AccessibilityObject* obj) : m_object(obj) { } - AccessibilityObjectWrapper() : m_object(0) { } - - AccessibilityObject* m_object; + 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 // AccessibilityObjectWrapperWin_h +#endif // WebKitPoint_h diff --git a/src/3rdparty/webkit/WebCore/page/chromium/AccessibilityObjectChromium.cpp b/src/3rdparty/webkit/WebCore/page/WebKitPoint.idl index e309ac8..1eefbc3 100644 --- a/src/3rdparty/webkit/WebCore/page/chromium/AccessibilityObjectChromium.cpp +++ b/src/3rdparty/webkit/WebCore/page/WebKitPoint.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * 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 @@ -10,10 +10,10 @@ * 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 + * 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 INC. OR + * 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 @@ -23,15 +23,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +module window { -#include "config.h" -#include "AccessibilityObject.h" + interface WebKitPoint { + attribute float x; + attribute float y; + }; -namespace WebCore { - -bool AccessibilityObject::accessibilityIgnoreAttachment() const -{ - return false; } - -} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/win/AXObjectCacheWin.cpp b/src/3rdparty/webkit/WebCore/page/android/DragControllerAndroid.cpp index da30ac5..94c1cbb 100644 --- a/src/3rdparty/webkit/WebCore/page/win/AXObjectCacheWin.cpp +++ b/src/3rdparty/webkit/WebCore/page/android/DragControllerAndroid.cpp @@ -1,5 +1,6 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +11,10 @@ * 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 + * 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 INC. OR + * 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 @@ -23,39 +24,35 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #include "config.h" -#include "AXObjectCache.h" +#include "DragController.h" -#include "AccessibilityObject.h" +#include "DragData.h" +#include "NotImplemented.h" namespace WebCore { -void AXObjectCache::detachWrapper(AccessibilityObject* obj) +bool DragController::isCopyKeyDown() { - // On Windows, AccessibilityObjects are created when get_accChildCount is - // called, but they are not wrapped until get_accChild is called, so this - // object may not have a wrapper. - if (AccessibilityObjectWrapper* wrapper = obj->wrapper()) - wrapper->detach(); + return false; } - -void AXObjectCache::attachWrapper(AccessibilityObject*) + +DragOperation DragController::dragOperation(DragData* dragData) { - // On Windows, AccessibilityObjects are wrapped when the accessibility - // software requests them via get_accChild. -} - -void AXObjectCache::postNotification(RenderObject*, const String&) -{ -} - -void AXObjectCache::postNotificationToElement(RenderObject*, const String&) -{ -} - -void AXObjectCache::handleFocusedUIElementChanged() -{ -} - -} // namespace WebCore + // FIXME: This logic is incomplete + notImplemented(); + if (dragData->containsURL()) + return DragOperationCopy; + + return DragOperationNone; +} + +const float DragController::DragImageAlpha = 1.0f; +static IntSize dummy; +const IntSize& DragController::maxDragImageSize() { return dummy; } +const int DragController::DragIconRightInset = 0; +const int DragController::DragIconBottomInset = 0; +const int DragController::LinkDragBorderInset = 0; +const int DragController::MaxOriginalImageArea = 0; + +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/android/EventHandlerAndroid.cpp b/src/3rdparty/webkit/WebCore/page/android/EventHandlerAndroid.cpp new file mode 100644 index 0000000..2464429 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/android/EventHandlerAndroid.cpp @@ -0,0 +1,129 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * + * 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. + */ +#define LOG_TAG "WebCore" + +#include "config.h" +#include "EventHandler.h" + +#include "FocusController.h" +#include "Frame.h" +#include "KeyboardEvent.h" +#include "MouseEventWithHitTestResults.h" +#include "Page.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformWheelEvent.h" +#include "RenderWidget.h" + +namespace WebCore { + +unsigned EventHandler::s_accessKeyModifiers = PlatformKeyboardEvent::AltKey; + +bool EventHandler::tabsToAllControls(KeyboardEvent* ) const +{ + return true; +} + +void EventHandler::focusDocumentView() +{ + if (Page* page = m_frame->page()) + page->focusController()->setFocusedFrame(m_frame); +} + +bool EventHandler::passWidgetMouseDownEventToWidget(const MouseEventWithHitTestResults& event) +{ + // Figure out which view to send the event to. + RenderObject* target = event.targetNode() ? event.targetNode()->renderer() : 0; + if (!target || !target->isWidget()) + return false; + + return passMouseDownEventToWidget(static_cast<RenderWidget*>(target)->widget()); +} + +bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget) +{ + return passMouseDownEventToWidget(renderWidget->widget()); +} + +// This function is used to route the mouse down event to the native widgets, it seems like a +// work around for the Mac platform which does not support double clicks, but browsers do. +bool EventHandler::passMouseDownEventToWidget(Widget* ) +{ + // return false so the normal propogation handles the event + return false; +} + +bool EventHandler::eventActivatedView(const PlatformMouseEvent& ) const +{ + notImplemented(); + return false; +} + +// This function is called for mouse events by FrameView::handleMousePressEvent(). +// It is used to ensure that events are sync'ed correctly between frames. For example +// if the user presses down in one frame and up in another frame, this function will +// returns true, and pass the event to the correct frame. +bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults& , Frame* , HitTestResult* ) +{ + notImplemented(); + return false; +} + +// This is called to route wheel events to child widgets when they are RenderWidget +// as the parent usually gets wheel event. Don't have a mouse with a wheel to confirm +// the operation of this function. +bool EventHandler::passWheelEventToWidget(PlatformWheelEvent& , Widget* ) +{ + notImplemented(); + return false; +} + +bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) +{ + return passSubframeEventToSubframe(mev, subframe); +} + +bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& mev, + Frame* subframe, HitTestResult* ) +{ + return passSubframeEventToSubframe(mev, subframe); +} + +bool EventHandler::passMouseReleaseEventToSubframe(MouseEventWithHitTestResults& mev, Frame* subframe) +{ + return passSubframeEventToSubframe(mev, subframe); +} + +class Clipboard : public RefCounted<Clipboard> { +}; + +PassRefPtr<Clipboard> EventHandler::createDraggingClipboard() const +{ + return PassRefPtr<Clipboard>(0); +} + +const double EventHandler::TextDragDelay = 0.0; + +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/android/InspectorControllerAndroid.cpp b/src/3rdparty/webkit/WebCore/page/android/InspectorControllerAndroid.cpp new file mode 100644 index 0000000..978bc25 --- /dev/null +++ b/src/3rdparty/webkit/WebCore/page/android/InspectorControllerAndroid.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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. + */ + +#include "config.h" +#include "InspectorController.h" + +#include "Frame.h" +#include "Node.h" +#include "Profile.h" + +// This stub file was created to avoid building and linking in all the +// Inspector codebase. If you would like to enable the Inspector, do the +// following steps: +// 1. Replace this file in WebCore/Android.mk with the common +// implementation, ie page/InsepctorController.cpp +// 2. Add the JS API files to JavaScriptCore/Android.mk: +// ? API/JSBase.cpp \ +// API/JSCallbackConstructor.cpp \ +// API/JSCallbackFunction.cpp \ +// API/JSCallbackObject.cpp \ +// API/JSClassRef.cpp \ +// API/JSContextRef.cpp \ +// API/JSObjectRef.cpp \ +// API/JSStringRef.cpp \ +// API/JSValueRef.cpp +// 3. Add the following LOCAL_C_INCLUDES to JavaScriptCore/Android.mk: +// ?$(LOCAL_PATH)/API \ +// $(LOCAL_PATH)/ForwardingHeaders \ +// $(LOCAL_PATH)/../../WebKit \ +// 4. Rebuild WebKit +// +// Note, for a functional Inspector, you must implement InspectorClientAndroid. + +namespace WebCore { + +struct InspectorResource : public RefCounted<InspectorResource> { +}; + +struct InspectorDatabaseResource : public RefCounted<InspectorDatabaseResource> { +}; + +InspectorController::InspectorController(Page*, InspectorClient*) + : m_startProfiling(this, 0) +{ +} + +InspectorController::~InspectorController() {} + +void InspectorController::windowScriptObjectAvailable() {} +void InspectorController::didCommitLoad(DocumentLoader*) {} +void InspectorController::identifierForInitialRequest(unsigned long, DocumentLoader*, ResourceRequest const&) {} +void InspectorController::willSendRequest(DocumentLoader*, unsigned long, ResourceRequest&, ResourceResponse const&) {} +void InspectorController::didReceiveResponse(DocumentLoader*, unsigned long, ResourceResponse const&) {} +void InspectorController::didReceiveContentLength(DocumentLoader*, unsigned long, int) {} +void InspectorController::didFinishLoading(DocumentLoader*, unsigned long) {} +void InspectorController::didLoadResourceFromMemoryCache(DocumentLoader*, ResourceRequest const&, ResourceResponse const&, int) {} +void InspectorController::frameDetachedFromParent(Frame*) {} + +void InspectorController::addMessageToConsole(MessageSource, MessageLevel, JSC::ExecState*, JSC::ArgList const&, unsigned int, String const&) {} +void InspectorController::addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID) {} +#if ENABLE(DATABASE) +void InspectorController::didOpenDatabase(Database*, String const&, String const&, String const&) {} +#endif +bool InspectorController::enabled() const { return false; } +void InspectorController::inspect(Node*) {} +bool InspectorController::windowVisible() { return false; } +void InspectorController::addProfile(PassRefPtr<JSC::Profile>, unsigned int, const JSC::UString&) {} +void InspectorController::inspectedPageDestroyed() {} +void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, JSC::UString& sourceString) {} + +void InspectorController::inspectedWindowScriptObjectCleared(Frame* frame) {} +void InspectorController::startGroup(MessageSource source, JSC::ExecState* exec, const JSC::ArgList& arguments, unsigned lineNumber, const String& sourceURL) {} +void InspectorController::endGroup(MessageSource source, unsigned lineNumber, const String& sourceURL) {} +void InspectorController::startTiming(const JSC::UString& title) {} +bool InspectorController::stopTiming(const JSC::UString& title, double& elapsed) { return false; } +void InspectorController::count(const JSC::UString& title, unsigned lineNumber, const String& sourceID) {} + +void InspectorController::mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags) {} +void InspectorController::handleMousePressOnNode(Node*) {} +void InspectorController::failedToParseSource(JSC::ExecState* exec, const JSC::SourceCode& source, int errorLine, const JSC::UString& errorMessage) {} +void InspectorController::didParseSource(JSC::ExecState* exec, const JSC::SourceCode& source) {} +void InspectorController::didPause() {} + +} // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.cpp b/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.cpp index 60bc774..7b8a189 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.cpp +++ b/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.cpp @@ -29,7 +29,9 @@ #include "config.h" #include "AnimationBase.h" -#include "AnimationController.h" +#include "AnimationControllerPrivate.h" +#include "CSSMutableStyleDeclaration.h" +#include "CSSPropertyLonghand.h" #include "CSSPropertyNames.h" #include "CString.h" #include "CompositeAnimation.h" @@ -41,11 +43,15 @@ #include "ImplicitAnimation.h" #include "KeyframeAnimation.h" #include "MatrixTransformOperation.h" -#include "RenderObject.h" +#include "Matrix3DTransformOperation.h" +#include "RenderBox.h" #include "RenderStyle.h" -#include "SystemTime.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 @@ -79,7 +85,11 @@ static inline float blendFunc(const AnimationBase*, float from, float to, double } static inline Color blendFunc(const AnimationBase* anim, const Color& from, const Color& to, double progress) -{ +{ + // We need to preserve the state of the valid flag at the end of the animation + if (progress == 1 && !to.isValid()) + return Color(); + return Color(blendFunc(anim, from.red(), to.red(), progress), blendFunc(anim, from.green(), to.green(), progress), blendFunc(anim, from.blue(), to.blue(), progress), @@ -91,6 +101,12 @@ static inline Length blendFunc(const AnimationBase*, const Length& from, const L return to.blend(from, progress); } +static inline LengthSize blendFunc(const AnimationBase* anim, const LengthSize& from, const LengthSize& to, double progress) +{ + return LengthSize(blendFunc(anim, from.width(), to.width(), progress), + blendFunc(anim, from.height(), to.height(), progress)); +} + static inline IntSize blendFunc(const AnimationBase* anim, const IntSize& from, const IntSize& to, double progress) { return IntSize(blendFunc(anim, from.width(), to.width(), progress), @@ -129,7 +145,7 @@ static inline TransformOperations blendFunc(const AnimationBase* anim, const Tra } } else { // Convert the TransformOperations into matrices - IntSize size = anim->renderer()->borderBox().size(); + IntSize size = anim->renderer()->isBox() ? toRenderBox(anim->renderer())->borderBoxRect().size() : IntSize(); TransformationMatrix fromT; TransformationMatrix toT; from.apply(size, fromT); @@ -138,7 +154,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; } @@ -155,6 +171,11 @@ static inline EVisibility blendFunc(const AnimationBase* anim, EVisibility from, return result > 0. ? VISIBLE : (to != VISIBLE ? to : from); } +class PropertyWrapperBase; + +static void addShorthandProperties(); +static PropertyWrapperBase* wrapperForProperty(int propertyID); + class PropertyWrapperBase { public: PropertyWrapperBase(int prop) @@ -163,11 +184,17 @@ public: } virtual ~PropertyWrapperBase() { } + + virtual bool isShorthandWrapper() const { return false; } virtual bool equals(const RenderStyle* a, const RenderStyle* b) const = 0; virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const = 0; int property() const { return m_prop; } +#if USE(ACCELERATED_COMPOSITING) + virtual bool animationIsAccelerated() const { return false; } +#endif + private: int m_prop; }; @@ -185,7 +212,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; @@ -214,6 +241,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)) @@ -227,7 +289,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; @@ -289,9 +351,48 @@ private: void (RenderStyle::*m_setter)(const Color&); }; +class ShorthandPropertyWrapper : public PropertyWrapperBase { +public: + ShorthandPropertyWrapper(int property, const CSSPropertyLonghand& longhand) + : PropertyWrapperBase(property) + { + for (unsigned i = 0; i < longhand.length(); ++i) { + PropertyWrapperBase* wrapper = wrapperForProperty(longhand.properties()[i]); + if (wrapper) + m_propertyWrappers.append(wrapper); + } + } + + virtual bool isShorthandWrapper() const { return true; } + + virtual bool equals(const RenderStyle* a, const RenderStyle* b) const + { + Vector<PropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end(); + for (Vector<PropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) { + if (!(*it)->equals(a, b)) + return false; + } + return true; + } + + virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const + { + Vector<PropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end(); + for (Vector<PropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) + (*it)->blend(anim, dst, a, b, progress); + } + +private: + Vector<PropertyWrapperBase*> m_propertyWrappers; +}; + + static Vector<PropertyWrapperBase*>* gPropertyWrappers = 0; static int gPropertyWrapperMap[numCSSProperties]; +static const int cInvalidPropertyWrapperIndex = -1; + + static void ensurePropertyMap() { // FIXME: This data is never destroyed. Maybe we should ref count it and toss it when the last AnimationController is destroyed? @@ -317,9 +418,17 @@ 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<Length>(CSSPropertyBackgroundPositionX, &RenderStyle::backgroundXPosition, &RenderStyle::setBackgroundXPosition)); + gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyBackgroundPositionY, &RenderStyle::backgroundYPosition, &RenderStyle::setBackgroundYPosition)); + gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyWebkitBackgroundSize, &RenderStyle::backgroundSize, &RenderStyle::setBackgroundSize)); + + gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitMaskPositionX, &RenderStyle::maskXPosition, &RenderStyle::setMaskXPosition)); + gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitMaskPositionY, &RenderStyle::maskYPosition, &RenderStyle::setMaskYPosition)); + gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyWebkitMaskSize, &RenderStyle::maskSize, &RenderStyle::setMaskSize)); + gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyFontSize, &RenderStyle::fontSize, &RenderStyle::setBlendedFontSize)); gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnRuleWidth, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth)); gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap)); @@ -333,15 +442,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)); @@ -361,30 +482,107 @@ static void ensurePropertyMap() gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeOpacity, &RenderStyle::strokeOpacity, &RenderStyle::setStrokeOpacity)); #endif + // TODO: + // + // CSSPropertyMinWidth, CSSPropertyMaxWidth, CSSPropertyMinHeight, CSSPropertyMaxHeight + // CSSPropertyTextIndent + // CSSPropertyVerticalAlign + // + // Compound properties that have components that should be animatable: + // + // CSSPropertyWebkitColumns + // CSSPropertyWebkitBoxReflect + // Make sure unused slots have a value - for (unsigned int i = 0; i < (unsigned int) numCSSProperties; ++i) - gPropertyWrapperMap[i] = CSSPropertyInvalid; + for (unsigned int i = 0; i < static_cast<unsigned int>(numCSSProperties); ++i) + gPropertyWrapperMap[i] = cInvalidPropertyWrapperIndex; + // First we put the non-shorthand property wrappers into the map, so the shorthand-building + // code can find them. size_t n = gPropertyWrappers->size(); for (unsigned int i = 0; i < n; ++i) { ASSERT((*gPropertyWrappers)[i]->property() - firstCSSProperty < numCSSProperties); gPropertyWrapperMap[(*gPropertyWrappers)[i]->property() - firstCSSProperty] = i; } + + // Now add the shorthand wrappers. + addShorthandProperties(); + } +} + +static void addPropertyWrapper(int propertyID, PropertyWrapperBase* wrapper) +{ + int propIndex = propertyID - firstCSSProperty; + + ASSERT(gPropertyWrapperMap[propIndex] == cInvalidPropertyWrapperIndex); + + unsigned wrapperIndex = gPropertyWrappers->size(); + gPropertyWrappers->append(wrapper); + gPropertyWrapperMap[propIndex] = wrapperIndex; +} + +static void addShorthandProperties() +{ + static const int animatableShorthandProperties[] = { + CSSPropertyBackground, // for background-color, background-position + CSSPropertyBackgroundPosition, + CSSPropertyWebkitMask, // for mask-position + CSSPropertyWebkitMaskPosition, + CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft, + CSSPropertyBorderColor, + CSSPropertyBorderWidth, + CSSPropertyBorder, + CSSPropertyBorderSpacing, + CSSPropertyMargin, + CSSPropertyOutline, + CSSPropertyPadding, + CSSPropertyWebkitTextStroke, + CSSPropertyWebkitColumnRule, + CSSPropertyWebkitBorderRadius, + CSSPropertyWebkitTransformOrigin + }; + + for (unsigned i = 0; i < sizeof(animatableShorthandProperties) / sizeof(animatableShorthandProperties[0]); ++i) { + int propertyID = animatableShorthandProperties[i]; + CSSPropertyLonghand longhand = longhandForProperty(propertyID); + if (longhand.length() > 0) + addPropertyWrapper(propertyID, new ShorthandPropertyWrapper(propertyID, longhand)); + } + + // 'font' is not in the shorthand map. + static const int animatableFontProperties[] = { + CSSPropertyFontSize, + CSSPropertyFontWeight + }; + + CSSPropertyLonghand fontLonghand(animatableFontProperties, sizeof(animatableFontProperties) / sizeof(animatableFontProperties[0])); + addPropertyWrapper(CSSPropertyFont, new ShorthandPropertyWrapper(CSSPropertyFont, fontLonghand)); +} + +static PropertyWrapperBase* wrapperForProperty(int propertyID) +{ + int propIndex = propertyID - firstCSSProperty; + if (propIndex >= 0 && propIndex < numCSSProperties) { + int wrapperIndex = gPropertyWrapperMap[propIndex]; + if (wrapperIndex >= 0) + return (*gPropertyWrappers)[wrapperIndex]; } + return 0; } 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) { // Compute the total duration m_totalDuration = -1; @@ -394,8 +592,8 @@ AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer AnimationBase::~AnimationBase() { - if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->setWaitingForStyleAvailable(false); + m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); + m_compAnim->animationController()->removeFromStartTimeResponseWaitList(this); } bool AnimationBase::propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b) @@ -404,27 +602,28 @@ bool AnimationBase::propertiesEqual(int prop, const RenderStyle* a, const Render if (prop == cAnimateAll) { size_t n = gPropertyWrappers->size(); for (unsigned int i = 0; i < n; ++i) { - if (!(*gPropertyWrappers)[i]->equals(a, b)) + PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i]; + // No point comparing shorthand wrappers for 'all'. + if (!wrapper->isShorthandWrapper() && !wrapper->equals(a, b)) return false; } } else { - int propIndex = prop - firstCSSProperty; - - if (propIndex >= 0 && propIndex < numCSSProperties) { - int i = gPropertyWrapperMap[propIndex]; - return i >= 0 ? (*gPropertyWrappers)[i]->equals(a, b) : true; - } + PropertyWrapperBase* wrapper = wrapperForProperty(prop); + if (wrapper) + return wrapper->equals(a, b); } return true; } -int AnimationBase::getPropertyAtIndex(int i) +int AnimationBase::getPropertyAtIndex(int i, bool& isShorthand) { ensurePropertyMap(); if (i < 0 || i >= static_cast<int>(gPropertyWrappers->size())) return CSSPropertyInvalid; - return (*gPropertyWrappers)[i]->property(); + PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i]; + isShorthand = wrapper->isShorthandWrapper(); + return wrapper->property(); } int AnimationBase::getNumProperties() @@ -437,41 +636,35 @@ int AnimationBase::getNumProperties() bool AnimationBase::blendProperties(const AnimationBase* anim, int prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) { ASSERT(prop != cAnimateAll); - // FIXME: Why can this happen? - - ensurePropertyMap(); - if (prop == cAnimateAll) { - bool needsTimer = false; - - size_t n = gPropertyWrappers->size(); - for (unsigned int i = 0; i < n; ++i) { - PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i]; - if (!wrapper->equals(a, b)) { - wrapper->blend(anim, dst, a, b, progress); - needsTimer = true; - } - } - return needsTimer; - } - int propIndex = prop - firstCSSProperty; - if (propIndex >= 0 && propIndex < numCSSProperties) { - int i = gPropertyWrapperMap[propIndex]; - if (i >= 0) { - PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i]; - wrapper->blend(anim, dst, a, b, progress); - return true; - } + ensurePropertyMap(); + 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; } -void AnimationBase::setChanged(Node* node) +#if USE(ACCELERATED_COMPOSITING) +bool AnimationBase::animationOfPropertyIsAccelerated(int prop) +{ + ensurePropertyMap(); + PropertyWrapperBase* wrapper = wrapperForProperty(prop); + return wrapper ? wrapper->animationIsAccelerated() : false; +} +#endif + +void AnimationBase::setNeedsStyleRecalc(Node* node) { ASSERT(!node || (node->document() && !node->document()->inPageCache())); if (node) - node->setChanged(AnimationStyleChange); + node->setNeedsStyleRecalc(AnimationStyleChange); } double AnimationBase::duration() const @@ -494,20 +687,19 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) // If we get AnimationStateInputRestartAnimation then we force a new animation, regardless of state. if (input == AnimationStateInputMakeNew) { if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->setWaitingForStyleAvailable(false); + m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); m_animState = AnimationStateNew; m_startTime = 0; m_pauseTime = -1; m_requestedStartTime = 0; m_nextIterationDuration = -1; - m_waitedForResponse = false; endAnimation(false); return; } if (input == AnimationStateInputRestartAnimation) { if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->setWaitingForStyleAvailable(false); + m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); m_animState = AnimationStateNew; m_startTime = 0; m_pauseTime = -1; @@ -522,7 +714,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) if (input == AnimationStateInputEndAnimation) { if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->setWaitingForStyleAvailable(false); + m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); m_animState = AnimationStateDone; endAnimation(true); return; @@ -547,11 +739,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; } @@ -563,11 +754,11 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) ASSERT(param >= 0); // Start timer has fired, tell the animation to start and wait for it to respond with start time m_animState = AnimationStateStartWaitStyleAvailable; - m_compAnim->setWaitingForStyleAvailable(true); + m_compAnim->animationController()->addToStyleAvailableWaitList(this); // Trigger a render so we can start the animation - setChanged(m_object->element()); - m_object->animation()->startUpdateRenderingDispatcher(); + if (m_object) + m_compAnim->animationController()->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 @@ -578,8 +769,6 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) case AnimationStateStartWaitStyleAvailable: ASSERT(input == AnimationStateInputStyleAvailable || input == AnimationStateInputPlayStatePaused); - m_compAnim->setWaitingForStyleAvailable(false); - // Start timer has fired, tell the animation to start and wait for it to respond with start time m_animState = AnimationStateStartWaitResponse; @@ -589,12 +778,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->animationController()->addToStartTimeResponseWaitList(this, started); + m_fallbackAnimating = !started; + } break; case AnimationStateStartWaitResponse: ASSERT(input == AnimationStateInputStartTimeSet || input == AnimationStateInputPlayStatePaused); @@ -608,11 +803,9 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) // Decide whether to go into looping or ending state goIntoEndingOrLoopingState(); - // Trigger a render so we can start the animation - if (m_object) { - setChanged(m_object->element()); - m_compAnim->animationController()->startUpdateRenderingDispatcher(); - } + // Dispatch updateStyleIfNeeded so we can start the animation + if (m_object) + m_compAnim->animationController()->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 @@ -652,8 +845,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) resumeOverriddenAnimations(); // Fire off another style change so we can set the final value - setChanged(m_object->element()); - m_object->animation()->startUpdateRenderingDispatcher(); + m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node()); } } else { // We are pausing while running. Cancel the animation and wait @@ -680,8 +872,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; @@ -693,11 +896,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(m_startTime); + m_compAnim->animationController()->addToStartTimeResponseWaitList(this, started); + m_fallbackAnimating = !started; + } break; case AnimationStateDone: // We're done. Stay in this state until we are deleted @@ -726,14 +934,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 @@ -759,18 +969,20 @@ void AnimationBase::updatePlayState(bool run) updateStateMachine(run ? AnimationStateInputPlayStateRunnning : AnimationStateInputPlayStatePaused, -1); } -double AnimationBase::willNeedService() const +double AnimationBase::timeToNextService() { // 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; } @@ -780,9 +992,7 @@ double AnimationBase::progress(double scale, double offset, const TimingFunction if (preActive()) return 0; - double elapsedTime = running() && !paused() ? (beginAnimationUpdateTime() - m_startTime) : (m_pauseTime - m_startTime); - if (running() && elapsedTime < 0) - return 0; + double elapsedTime = getElapsedTime(); double dur = m_animation->duration(); if (m_animation->iterationCount() > 0) @@ -819,31 +1029,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) @@ -857,4 +1076,15 @@ double AnimationBase::beginAnimationUpdateTime() const return m_compAnim->animationController()->beginAnimationUpdateTime(); } +double AnimationBase::getElapsedTime() const +{ + if (paused()) + return m_pauseTime - m_startTime; + if (m_startTime <= 0) + return 0; + if (postActive()) + return 1; + return beginAnimationUpdateTime() - m_startTime; +} + } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.h b/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.h index 3a5cb85..8f55a8e 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.h +++ b/src/3rdparty/webkit/WebCore/page/animation/AnimationBase.h @@ -45,7 +45,7 @@ class RenderStyle; class TimingFunction; class AnimationBase : public RefCounted<AnimationBase> { - friend class CompositeAnimationPrivate; + friend class CompositeAnimation; public: AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim); @@ -54,7 +54,6 @@ public: RenderObject* renderer() const { return m_object; } void clearRenderer() { m_object = 0; } - double startTime() const { return m_startTime; } double duration() const; // Animations and Transitions go through the states below. When entering the STARTED state @@ -95,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); @@ -118,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 timeToNextService(); 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; } @@ -143,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); @@ -155,6 +160,21 @@ public: double beginAnimationUpdateTime() const; + double getElapsedTime() const; + + AnimationBase* next() const { return m_next; } + void setNext(AnimationBase* animation) { m_next = animation; } + + void styleAvailable() + { + ASSERT(waitingForStyleAvailable()); + updateStateMachine(AnimationBase::AnimationStateInputStyleAvailable, -1); + } + +#if USE(ACCELERATED_COMPOSITING) + static bool animationOfPropertyIsAccelerated(int prop); +#endif + protected: virtual void overrideAnimations() { } virtual void resumeOverriddenAnimations() { } @@ -170,19 +190,22 @@ protected: void goIntoEndingOrLoopingState(); + bool isFallbackAnimating() const { return m_fallbackAnimating; } + static bool propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b); - static int getPropertyAtIndex(int); + 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 setNeedsStyleRecalc(Node*); - 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; @@ -190,8 +213,11 @@ 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; + + AnimationBase* m_next; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp b/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp index 3b6cfcc..58a1f5b 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp +++ b/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007, 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 @@ -28,81 +28,32 @@ #include "config.h" #include "AnimationController.h" -#include "CompositeAnimation.h" + +#include "AnimationBase.h" +#include "AnimationControllerPrivate.h" #include "CSSParser.h" +#include "CompositeAnimation.h" #include "EventNames.h" #include "Frame.h" -#include "SystemTime.h" -#include "Timer.h" +#include "RenderView.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); - - 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; } - -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; - - double m_beginAnimationUpdateTime; -}; - AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame) : m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired) - , m_updateRenderingDispatcher(this, &AnimationControllerPrivate::updateRenderingDispatcherFired) + , m_updateStyleIfNeededDispatcher(this, &AnimationControllerPrivate::updateStyleIfNeededDispatcherFired) , m_frame(frame) , m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet) + , m_styleAvailableWaiters(0) + , m_lastStyleAvailableWaiter(0) + , m_responseWaiters(0) + , m_lastResponseWaiter(0) + , m_waitingForAResponse(false) { } @@ -114,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; @@ -123,7 +74,7 @@ PassRefPtr<CompositeAnimation> AnimationControllerPrivate::accessCompositeAnimat bool AnimationControllerPrivate::clear(RenderObject* renderer) { // Return false if we didn't do anything OR we are suspended (so we don't try to - // do a setChanged() when suspended). + // do a setNeedsStyleRecalc() when suspended). PassRefPtr<CompositeAnimation> animation = m_compositeAnimations.take(renderer); if (!animation) return false; @@ -131,23 +82,6 @@ bool AnimationControllerPrivate::clear(RenderObject* renderer) return animation->isSuspended(); } -void AnimationControllerPrivate::styleAvailable() -{ - // styleAvailable() can call event handlers which would ultimately delete a CompositeAnimation - // from the m_compositeAnimations table. So we can't iterate it directly. We will instead build - // a list of CompositeAnimations which need the styleAvailable() call iterate over that. - Vector<RefPtr<CompositeAnimation> > list; - - RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); - for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) - if (it->second->isWaitingForStyleAvailable()) - list.append(it->second); - - Vector<RefPtr<CompositeAnimation> >::const_iterator listEnd = list.end(); - for (Vector<RefPtr<CompositeAnimation> >::const_iterator it = list.begin(); it != listEnd; ++it) - (*it)->styleAvailable(); -} - void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = false*/) { double needsService = -1; @@ -155,16 +89,16 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { - RefPtr<CompositeAnimation> compAnim = it->second; - if (!compAnim->isSuspended()) { - double t = compAnim->willNeedService(); + CompositeAnimation* compAnim = it->second.get(); + if (!compAnim->isSuspended() && compAnim->hasAnimations()) { + double t = compAnim->timeToNextService(); if (t != -1 && (t < needsService || needsService == -1)) 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); + node->setNeedsStyleRecalc(AnimationStyleChange); calledSetChanged = true; } else @@ -174,7 +108,7 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa } if (calledSetChanged) - m_frame->document()->updateRendering(); + m_frame->document()->updateStyleIfNeeded(); // If we want service immediately, we start a repeating timer to reduce the overhead of starting if (needsService == 0) { @@ -196,11 +130,11 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa m_animationTimer.startOneShot(needsService); } -void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*) +void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*) { // fire all the events - Vector<EventToDispatch>::const_iterator end = m_eventsToDispatch.end(); - for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != end; ++it) { + Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = m_eventsToDispatch.end(); + for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) { if (it->eventType == eventNames().webkitTransitionEndEvent) it->element->dispatchWebKitTransitionEvent(it->eventType,it->name, it->elapsedTime); else @@ -209,14 +143,35 @@ void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationC m_eventsToDispatch.clear(); - if (m_frame && m_frame->document()) - m_frame->document()->updateRendering(); + // call setChanged on all the elements + Vector<RefPtr<Node> >::const_iterator nodeChangesToDispatchEnd = m_nodeChangesToDispatch.end(); + for (Vector<RefPtr<Node> >::const_iterator it = m_nodeChangesToDispatch.begin(); it != nodeChangesToDispatchEnd; ++it) + (*it)->setNeedsStyleRecalc(AnimationStyleChange); + + m_nodeChangesToDispatch.clear(); + + if (m_frame) + m_frame->document()->updateStyleIfNeeded(); + + // We can now safely remove any animations or transitions that are finished. + // We can't remove them any earlier because we might get a false restart of + // a transition. This can happen because we have not yet set the final property + // value until we call the rendering dispatcher. So this can make the current + // style slightly different from the desired final style (because our last + // animation step was, say 0.9999 or something). And we need to remove them + // here because if there are no more animations running we'll never get back + // into the animation code to clean them up. + RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); + for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { + CompositeAnimation* compAnim = it->second.get(); + compAnim->cleanupFinishedAnimations(); // will not modify m_compositeAnimations, so OK to call while iterating + } } -void AnimationControllerPrivate::startUpdateRenderingDispatcher() +void AnimationControllerPrivate::startUpdateStyleIfNeededDispatcher() { - if (!m_updateRenderingDispatcher.isActive()) - m_updateRenderingDispatcher.startOneShot(0); + if (!m_updateStyleIfNeededDispatcher.isActive()) + m_updateStyleIfNeededDispatcher.startOneShot(0); } void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime) @@ -228,21 +183,31 @@ void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, event.name = name; event.elapsedTime = elapsedTime; - startUpdateRenderingDispatcher(); + startUpdateStyleIfNeededDispatcher(); +} + +void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node) +{ + ASSERT(!node || (node->document() && !node->document()->inPageCache())); + if (!node) + return; + + m_nodeChangesToDispatch.append(node); + startUpdateStyleIfNeededDispatcher(); } 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 - // updateRendering. It will then call back to us with new information. + // updateStyleIfNeeded. It will then call back to us with new information. 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) @@ -253,12 +218,15 @@ bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* ren void AnimationControllerPrivate::suspendAnimations(Document* document) { + setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); + RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { RenderObject* renderer = it->first; - RefPtr<CompositeAnimation> compAnim = it->second; - if (renderer->document() == document) + if (renderer->document() == document) { + CompositeAnimation* compAnim = it->second.get(); compAnim->suspendAnimations(); + } } updateAnimationTimer(); @@ -266,12 +234,15 @@ void AnimationControllerPrivate::suspendAnimations(Document* document) void AnimationControllerPrivate::resumeAnimations(Document* document) { + setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); + RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { RenderObject* renderer = it->first; - RefPtr<CompositeAnimation> compAnim = it->second; - if (renderer->document() == document) + if (renderer->document() == document) { + CompositeAnimation* compAnim = it->second.get(); compAnim->resumeAnimations(); + } } updateAnimationTimer(); @@ -287,7 +258,8 @@ bool AnimationControllerPrivate::pauseAnimationAtTime(RenderObject* renderer, co return false; if (compAnim->pauseAnimationAtTime(name, t)) { - renderer->node()->setChanged(AnimationStyleChange); + renderer->node()->setNeedsStyleRecalc(AnimationStyleChange); + startUpdateStyleIfNeededDispatcher(); return true; } @@ -304,13 +276,40 @@ bool AnimationControllerPrivate::pauseTransitionAtTime(RenderObject* renderer, c return false; if (compAnim->pauseTransitionAtTime(cssPropertyID(property), t)) { - renderer->node()->setChanged(AnimationStyleChange); + renderer->node()->setNeedsStyleRecalc(AnimationStyleChange); + startUpdateStyleIfNeededDispatcher(); 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; @@ -324,9 +323,119 @@ unsigned AnimationControllerPrivate::numberOfActiveAnimations() const return count; } +void AnimationControllerPrivate::addToStyleAvailableWaitList(AnimationBase* animation) +{ + ASSERT(!animation->next()); + + if (m_styleAvailableWaiters) + m_lastStyleAvailableWaiter->setNext(animation); + else + m_styleAvailableWaiters = animation; + + m_lastStyleAvailableWaiter = animation; + animation->setNext(0); +} + +void AnimationControllerPrivate::removeFromStyleAvailableWaitList(AnimationBase* animationToRemove) +{ + AnimationBase* prevAnimation = 0; + for (AnimationBase* animation = m_styleAvailableWaiters; animation; animation = animation->next()) { + if (animation == animationToRemove) { + if (prevAnimation) + prevAnimation->setNext(animation->next()); + else + m_styleAvailableWaiters = animation->next(); + + if (m_lastStyleAvailableWaiter == animation) + m_lastStyleAvailableWaiter = prevAnimation; + + animationToRemove->setNext(0); + } + } +} + +void AnimationControllerPrivate::styleAvailable() +{ + // Go through list of waiters and send them on their way + 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 + // updateStyleIfNeeded 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)) - , m_numStyleAvailableWaiters(0) { } @@ -341,9 +450,9 @@ 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); + node->setNeedsStyleRecalc(AnimationStyleChange); } } @@ -358,11 +467,15 @@ PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject* rend if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) && (!newStyle->animations() && !newStyle->transitions())) return newStyle; + // Don't run transitions when printing. + if (renderer->view()->printing()) + return newStyle; + // Fetch our current set of implicit animations from a hashtable. We then compare them // 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); @@ -379,16 +492,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) @@ -406,7 +517,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); } @@ -421,29 +532,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::styleAvailable() -{ - if (!m_numStyleAvailableWaiters) - return; - - m_data->styleAvailable(); -} - -double AnimationController::beginAnimationUpdateTime() -{ - return m_data->beginAnimationUpdateTime(); -} - void AnimationController::beginAnimationUpdate() { m_data->setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); @@ -451,6 +539,17 @@ void AnimationController::beginAnimationUpdate() void AnimationController::endAnimationUpdate() { + m_data->endAnimationUpdate(); +} + +bool AnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property) +{ +#if USE(ACCELERATED_COMPOSITING) + return AnimationBase::animationOfPropertyIsAccelerated(property); +#else + UNUSED_PARAM(property); + return false; +#endif } } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/animation/AnimationController.h b/src/3rdparty/webkit/WebCore/page/animation/AnimationController.h index 45d0c7d..db82618 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/AnimationController.h +++ b/src/3rdparty/webkit/WebCore/page/animation/AnimationController.h @@ -29,10 +29,12 @@ #ifndef AnimationController_h #define AnimationController_h +#include "CSSPropertyNames.h" #include <wtf/Forward.h> namespace WebCore { +class AnimationBase; class AnimationControllerPrivate; class AtomicString; class Document; @@ -50,40 +52,27 @@ 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 styleAvailable(); - - void setWaitingForStyleAvailable(bool waiting) - { - if (waiting) - m_numStyleAvailableWaiters++; - else - m_numStyleAvailableWaiters--; - } - - double beginAnimationUpdateTime(); - void beginAnimationUpdate(); void endAnimationUpdate(); + + static bool supportsAcceleratedAnimationOfProperty(CSSPropertyID); private: AnimationControllerPrivate* m_data; - unsigned m_numStyleAvailableWaiters; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/animation/AnimationControllerPrivate.h b/src/3rdparty/webkit/WebCore/page/animation/AnimationControllerPrivate.h new file mode 100644 index 0000000..359b9b5 --- /dev/null +++ b/src/3rdparty/webkit/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 updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*); + void startUpdateStyleIfNeededDispatcher(); + 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_updateStyleIfNeededDispatcher; + 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/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.cpp b/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.cpp index 57cb774..d60455a 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.cpp +++ b/src/3rdparty/webkit/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" @@ -38,96 +38,37 @@ namespace WebCore { -class CompositeAnimationPrivate { -public: - CompositeAnimationPrivate(AnimationController* animationController, CompositeAnimation* compositeAnimation) - : m_isSuspended(false) - , m_animationController(animationController) - , m_compositeAnimation(compositeAnimation) - , m_numStyleAvailableWaiters(0) - { - } - - ~CompositeAnimationPrivate(); - - void clearRenderer(); - - PassRefPtr<RenderStyle> animate(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle); - - AnimationController* animationController() { return m_animationController; } - - void setAnimating(bool); - double willNeedService() const; - - PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property); - - void cleanupFinishedAnimations(RenderObject*); - - void setAnimationStartTime(double t); - void setTransitionStartTime(int property, double t); - - void suspendAnimations(); - void resumeAnimations(); - bool isSuspended() const { return m_isSuspended; } - - void overrideImplicitAnimations(int property); - void resumeOverriddenImplicitAnimations(int property); - - void styleAvailable(); - - bool isAnimatingProperty(int property, bool isRunningNow) const; - - void setWaitingForStyleAvailable(bool); - bool isWaitingForStyleAvailable() const { return m_numStyleAvailableWaiters > 0; } - - bool pauseAnimationAtTime(const AtomicString& name, double t); - bool pauseTransitionAtTime(int property, double t); - unsigned numberOfActiveAnimations() const; - -protected: - void updateTransitions(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle); - void updateKeyframeAnimations(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle); - -private: - typedef HashMap<int, RefPtr<ImplicitAnimation> > CSSPropertyTransitionsMap; - typedef HashMap<AtomicStringImpl*, RefPtr<KeyframeAnimation> > AnimationNameMap; - - CSSPropertyTransitionsMap m_transitions; - AnimationNameMap m_keyframeAnimations; - bool m_isSuspended; - AnimationController* m_animationController; - CompositeAnimation* m_compositeAnimation; - unsigned m_numStyleAvailableWaiters; -}; - -CompositeAnimationPrivate::~CompositeAnimationPrivate() +CompositeAnimation::~CompositeAnimation() { // Toss the refs to all animations m_transitions.clear(); m_keyframeAnimations.clear(); } -void CompositeAnimationPrivate::clearRenderer() +void CompositeAnimation::clearRenderer() { - // Clear the renderers from all running animations, in case we are in the middle of - // an animation callback (see https://bugs.webkit.org/show_bug.cgi?id=22052) - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* transition = it->second.get(); - transition->clearRenderer(); + if (!m_transitions.isEmpty()) { + // Clear the renderers from all running animations, in case we are in the middle of + // an animation callback (see https://bugs.webkit.org/show_bug.cgi?id=22052) + CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); + for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { + ImplicitAnimation* transition = it->second.get(); + transition->clearRenderer(); + } } - - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->second.get(); - anim->clearRenderer(); + if (!m_keyframeAnimations.isEmpty()) { + AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); + for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { + KeyframeAnimation* anim = it->second.get(); + anim->clearRenderer(); + } } - - } - -void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) + +void CompositeAnimation::updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) { + RefPtr<RenderStyle> modifiedCurrentStyle; + // If currentStyle is null, we don't do transitions if (!currentStyle || !targetStyle->transitions()) return; @@ -148,12 +89,15 @@ void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, Render // through the loop. for (int propertyIndex = 0; propertyIndex < AnimationBase::getNumProperties(); ++propertyIndex) { if (all) { - // Get the next property - prop = AnimationBase::getPropertyAtIndex(propertyIndex); + // Get the next property which is not a shorthand. + bool isShorthand; + prop = AnimationBase::getPropertyAtIndex(propertyIndex, isShorthand); + if (isShorthand) + continue; } // ImplicitAnimations are always hashed by actual properties, never cAnimateAll - ASSERT(prop > firstCSSProperty && prop < (firstCSSProperty + numCSSProperties)); + ASSERT(prop >= firstCSSProperty && prop < (firstCSSProperty + numCSSProperties)); // If there is a running animation for this property, the transition is overridden // and we have to use the unanimatedStyle from the animation. We do the test @@ -166,14 +110,26 @@ void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, Render bool equal = true; if (implAnim) { - // This implAnim might not be an already running transition. It might be - // newly added to the list in a previous iteration. This would happen if - // you have both an explicit transition-property and 'all' in the same - // list. In this case, the latter one overrides the earlier one, so we - // behave as though this is a running animation being replaced. - if (!isActiveTransition) - m_transitions.remove(prop); - else if (!implAnim->isTargetPropertyEqual(prop, targetStyle)) { + // This might be a transition that is just finishing. That would be the case + // if it were postActive. But we still need to check for equality because + // it could be just finishing AND changing to a new goal state. + // + // This implAnim might also not be an already running transition. It might be + // newly added to the list in a previous iteration. This would happen if + // you have both an explicit transition-property and 'all' in the same + // 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; } @@ -182,9 +138,13 @@ void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, Render equal = !isActiveTransition || AnimationBase::propertiesEqual(prop, fromStyle, targetStyle); } - if (!equal) { + // We can be in this loop with an inactive transition (!isActiveTransition). We need + // to do that to check to see if we are canceling a transition. But we don't want to + // start one of the inactive transitions. So short circuit that here. (See + // <https://bugs.webkit.org/show_bug.cgi?id=24787> + if (!equal && isActiveTransition) { // 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, this, modifiedCurrentStyle ? modifiedCurrentStyle.get() : fromStyle)); } // We only need one pass for the single prop case @@ -194,7 +154,7 @@ void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, Render } } -void CompositeAnimationPrivate::updateKeyframeAnimations(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) +void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) { // Nothing to do if we don't have any animations, and didn't have any before if (m_keyframeAnimations.isEmpty() && !targetStyle->hasAnimations()) @@ -208,6 +168,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()) { @@ -232,9 +195,13 @@ void CompositeAnimationPrivate::updateKeyframeAnimations(RenderObject* renderer, keyframeAnim->setAnimation(anim); keyframeAnim->setIndex(i); } else if ((anim->duration() || anim->delay()) && anim->iterationCount()) { - keyframeAnim = KeyframeAnimation::create(const_cast<Animation*>(anim), renderer, i, m_compositeAnimation, currentStyle ? currentStyle : targetStyle); + keyframeAnim = KeyframeAnimation::create(const_cast<Animation*>(anim), renderer, i, this, 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()); } } @@ -252,7 +219,7 @@ void CompositeAnimationPrivate::updateKeyframeAnimations(RenderObject* renderer, m_keyframeAnimations.remove(animsToBeRemoved[j]); } -PassRefPtr<RenderStyle> CompositeAnimationPrivate::animate(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) +PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) { RefPtr<RenderStyle> resultStyle; @@ -265,279 +232,256 @@ PassRefPtr<RenderStyle> CompositeAnimationPrivate::animate(RenderObject* rendere if (currentStyle) { // Now that we have transition objects ready, let them know about the new goal state. We want them // to fill in a RenderStyle*& only if needed. - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - if (ImplicitAnimation* anim = it->second.get()) - anim->animate(m_compositeAnimation, renderer, currentStyle, targetStyle, resultStyle); + if (!m_transitions.isEmpty()) { + CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); + for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { + if (ImplicitAnimation* anim = it->second.get()) + anim->animate(this, renderer, currentStyle, targetStyle, resultStyle); + } } } // 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(this, renderer, currentStyle, targetStyle, resultStyle); } - cleanupFinishedAnimations(renderer); + cleanupFinishedAnimations(); return resultStyle ? resultStyle.release() : targetStyle; } -// "animating" means that something is running that requires the timer to keep firing -void CompositeAnimationPrivate::setAnimating(bool animating) +PassRefPtr<RenderStyle> CompositeAnimation::getAnimatedStyle() const { - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* transition = it->second.get(); - transition->setAnimating(animating); + 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; +} - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->second.get(); - anim->setAnimating(animating); +// "animating" means that something is running that requires the timer to keep firing +void CompositeAnimation::setAnimating(bool animating) +{ + if (!m_transitions.isEmpty()) { + CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); + for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { + ImplicitAnimation* transition = it->second.get(); + transition->setAnimating(animating); + } + } + if (!m_keyframeAnimations.isEmpty()) { + AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); + for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { + KeyframeAnimation* anim = it->second.get(); + anim->setAnimating(animating); + } } } -double CompositeAnimationPrivate::willNeedService() const +double CompositeAnimation::timeToNextService() const { // 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. double minT = -1; - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* transition = it->second.get(); - double t = transition ? transition->willNeedService() : -1; - if (t < minT || minT == -1) - minT = t; - if (minT == 0) - return 0; + if (!m_transitions.isEmpty()) { + CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); + for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { + ImplicitAnimation* transition = it->second.get(); + double t = transition ? transition->timeToNextService() : -1; + if (t < minT || minT == -1) + minT = t; + if (minT == 0) + return 0; + } } - - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* animation = it->second.get(); - double t = animation ? animation->willNeedService() : -1; - if (t < minT || minT == -1) - minT = t; - if (minT == 0) - return 0; + if (!m_keyframeAnimations.isEmpty()) { + AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); + for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { + KeyframeAnimation* animation = it->second.get(); + double t = animation ? animation->timeToNextService() : -1; + if (t < minT || minT == -1) + minT = t; + if (minT == 0) + return 0; + } } return minT; } -PassRefPtr<KeyframeAnimation> CompositeAnimationPrivate::getAnimationForProperty(int property) +PassRefPtr<KeyframeAnimation> CompositeAnimation::getAnimationForProperty(int property) const { RefPtr<KeyframeAnimation> retval; // We want to send back the last animation with the property if there are multiples. // So we need to iterate through all animations - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - RefPtr<KeyframeAnimation> anim = it->second; - if (anim->hasAnimationForProperty(property)) - retval = anim; + if (!m_keyframeAnimations.isEmpty()) { + AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); + for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { + RefPtr<KeyframeAnimation> anim = it->second; + if (anim->hasAnimationForProperty(property)) + retval = anim; + } } return retval; } -void CompositeAnimationPrivate::cleanupFinishedAnimations(RenderObject*) +void CompositeAnimation::cleanupFinishedAnimations() { if (isSuspended()) return; // Make a list of transitions to be deleted Vector<int> finishedTransitions; - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); + if (!m_transitions.isEmpty()) { + CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* anim = it->second.get(); - if (!anim) - continue; - if (anim->postActive()) - finishedTransitions.append(anim->animatingProperty()); + for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { + ImplicitAnimation* anim = it->second.get(); + if (!anim) + continue; + if (anim->postActive()) + finishedTransitions.append(anim->animatingProperty()); + } + + // Delete them + size_t finishedTransitionCount = finishedTransitions.size(); + for (size_t i = 0; i < finishedTransitionCount; ++i) + m_transitions.remove(finishedTransitions[i]); } - // Delete them - size_t finishedTransitionCount = finishedTransitions.size(); - for (size_t i = 0; i < finishedTransitionCount; ++i) - m_transitions.remove(finishedTransitions[i]); - // Make a list of animations to be deleted Vector<AtomicStringImpl*> finishedAnimations; - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); + if (!m_keyframeAnimations.isEmpty()) { + AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->second.get(); - if (!anim) - continue; - if (anim->postActive()) - finishedAnimations.append(anim->name().impl()); - } - - // Delete them - size_t finishedAnimationCount = finishedAnimations.size(); - for (size_t i = 0; i < finishedAnimationCount; ++i) - m_keyframeAnimations.remove(finishedAnimations[i]); -} + for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { + KeyframeAnimation* anim = it->second.get(); + if (!anim) + continue; + if (anim->postActive()) + finishedAnimations.append(anim->name().impl()); + } -void CompositeAnimationPrivate::setAnimationStartTime(double t) -{ - // Set start time on all animations waiting for it - 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); + // Delete them + size_t finishedAnimationCount = finishedAnimations.size(); + for (size_t i = 0; i < finishedAnimationCount; ++i) + m_keyframeAnimations.remove(finishedAnimations[i]); } } -void CompositeAnimationPrivate::setTransitionStartTime(int property, double t) -{ - // Set the start time for given property transition - 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() +void CompositeAnimation::suspendAnimations() { if (m_isSuspended) return; m_isSuspended = true; - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - if (KeyframeAnimation* anim = it->second.get()) - anim->updatePlayState(false); + if (!m_keyframeAnimations.isEmpty()) { + AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); + for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { + if (KeyframeAnimation* anim = it->second.get()) + anim->updatePlayState(false); + } } - - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* anim = it->second.get(); - if (anim && anim->hasStyle()) - anim->updatePlayState(false); + if (!m_transitions.isEmpty()) { + CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); + for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { + ImplicitAnimation* anim = it->second.get(); + if (anim && anim->hasStyle()) + anim->updatePlayState(false); + } } } -void CompositeAnimationPrivate::resumeAnimations() +void CompositeAnimation::resumeAnimations() { if (!m_isSuspended) return; m_isSuspended = false; - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->second.get(); - if (anim && anim->playStatePlaying()) - anim->updatePlayState(true); - } - - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* anim = it->second.get(); - if (anim && anim->hasStyle()) - anim->updatePlayState(true); + if (!m_keyframeAnimations.isEmpty()) { + AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); + for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { + KeyframeAnimation* anim = it->second.get(); + if (anim && anim->playStatePlaying()) + anim->updatePlayState(true); + } } -} -void CompositeAnimationPrivate::overrideImplicitAnimations(int property) -{ - 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->animatingProperty() == property) - anim->setOverridden(true); + if (!m_transitions.isEmpty()) { + CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); + for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { + ImplicitAnimation* anim = it->second.get(); + if (anim && anim->hasStyle()) + anim->updatePlayState(true); + } } } -void CompositeAnimationPrivate::resumeOverriddenImplicitAnimations(int property) +void CompositeAnimation::overrideImplicitAnimations(int property) { 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->animatingProperty() == property) - anim->setOverridden(false); + if (!m_transitions.isEmpty()) { + for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { + ImplicitAnimation* anim = it->second.get(); + if (anim && anim->animatingProperty() == property) + anim->setOverridden(true); + } } } -static inline bool compareAnimationIndices(RefPtr<KeyframeAnimation> a, const RefPtr<KeyframeAnimation> b) -{ - return a->index() < b->index(); -} - -void CompositeAnimationPrivate::styleAvailable() +void CompositeAnimation::resumeOverriddenImplicitAnimations(int property) { - if (m_numStyleAvailableWaiters == 0) - return; - - // We have to go through animations in the order in which they appear in - // the style, because order matters for additivity. - Vector<RefPtr<KeyframeAnimation> > animations(m_keyframeAnimations.size()); - copyValuesToVector(m_keyframeAnimations, animations); - - if (animations.size() > 1) - std::stable_sort(animations.begin(), animations.end(), compareAnimationIndices); - - for (size_t i = 0; i < animations.size(); ++i) { - KeyframeAnimation* anim = animations[i].get(); - if (anim && anim->waitingForStyleAvailable()) - anim->updateStateMachine(AnimationBase::AnimationStateInputStyleAvailable, -1); - } - - 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->waitingForStyleAvailable()) - anim->updateStateMachine(AnimationBase::AnimationStateInputStyleAvailable, -1); + 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->animatingProperty() == property) + anim->setOverridden(false); + } } } -bool CompositeAnimationPrivate::isAnimatingProperty(int property, bool isRunningNow) const +bool CompositeAnimation::isAnimatingProperty(int property, bool isRunningNow) const { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->second.get(); - if (anim && anim->isAnimatingProperty(property, isRunningNow)) - return true; + if (!m_keyframeAnimations.isEmpty()) { + AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); + for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { + KeyframeAnimation* anim = it->second.get(); + if (anim && anim->isAnimatingProperty(property, isRunningNow)) + return true; + } } - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* anim = it->second.get(); - if (anim && anim->isAnimatingProperty(property, isRunningNow)) - return true; + if (!m_transitions.isEmpty()) { + CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); + for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { + ImplicitAnimation* anim = it->second.get(); + if (anim && anim->isAnimatingProperty(property, isRunningNow)) + return true; + } } return false; } -void CompositeAnimationPrivate::setWaitingForStyleAvailable(bool waiting) -{ - if (waiting) - m_numStyleAvailableWaiters++; - else - m_numStyleAvailableWaiters--; - m_animationController->setWaitingForStyleAvailable(waiting); -} - -bool CompositeAnimationPrivate::pauseAnimationAtTime(const AtomicString& name, double t) +bool CompositeAnimation::pauseAnimationAtTime(const AtomicString& name, double t) { if (!name) return false; @@ -555,7 +499,7 @@ bool CompositeAnimationPrivate::pauseAnimationAtTime(const AtomicString& name, d return false; } -bool CompositeAnimationPrivate::pauseTransitionAtTime(int property, double t) +bool CompositeAnimation::pauseTransitionAtTime(int property, double t) { if ((property < firstCSSProperty) || (property >= firstCSSProperty + numCSSProperties)) return false; @@ -572,135 +516,29 @@ bool CompositeAnimationPrivate::pauseTransitionAtTime(int property, double t) return false; } -unsigned CompositeAnimationPrivate::numberOfActiveAnimations() const +unsigned CompositeAnimation::numberOfActiveAnimations() const { unsigned count = 0; - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->second.get(); - if (anim->running()) - ++count; + if (!m_keyframeAnimations.isEmpty()) { + AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); + for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { + KeyframeAnimation* anim = it->second.get(); + if (anim->running()) + ++count; + } } - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* anim = it->second.get(); - if (anim->running()) - ++count; + if (!m_transitions.isEmpty()) { + CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); + for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { + ImplicitAnimation* anim = it->second.get(); + if (anim->running()) + ++count; + } } return count; } -CompositeAnimation::CompositeAnimation(AnimationController* animationController) - : m_data(new CompositeAnimationPrivate(animationController, this)) -{ -} - -CompositeAnimation::~CompositeAnimation() -{ - delete m_data; -} - -AnimationController* CompositeAnimation::animationController() -{ - return m_data->animationController(); -} - -void CompositeAnimation::clearRenderer() -{ - m_data->clearRenderer(); -} - -PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) -{ - return m_data->animate(renderer, currentStyle, targetStyle); -} - -double CompositeAnimation::willNeedService() const -{ - return m_data->willNeedService(); -} - -void CompositeAnimation::setWaitingForStyleAvailable(bool b) -{ - m_data->setWaitingForStyleAvailable(b); -} - -bool CompositeAnimation::isWaitingForStyleAvailable() const -{ - return m_data->isWaitingForStyleAvailable(); -} - -void CompositeAnimation::suspendAnimations() -{ - m_data->suspendAnimations(); -} - -void CompositeAnimation::resumeAnimations() -{ - m_data->resumeAnimations(); -} - -bool CompositeAnimation::isSuspended() const -{ - return m_data->isSuspended(); -} - -void CompositeAnimation::styleAvailable() -{ - m_data->styleAvailable(); -} - -void CompositeAnimation::setAnimating(bool b) -{ - m_data->setAnimating(b); -} - -bool CompositeAnimation::isAnimatingProperty(int property, bool isRunningNow) const -{ - return m_data->isAnimatingProperty(property, isRunningNow); -} - -PassRefPtr<KeyframeAnimation> CompositeAnimation::getAnimationForProperty(int property) -{ - 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); -} - -void CompositeAnimation::resumeOverriddenImplicitAnimations(int property) -{ - m_data->resumeOverriddenImplicitAnimations(property); -} - -bool CompositeAnimation::pauseAnimationAtTime(const AtomicString& name, double t) -{ - return m_data->pauseAnimationAtTime(name, t); -} - -bool CompositeAnimation::pauseTransitionAtTime(int property, double t) -{ - return m_data->pauseTransitionAtTime(property, t); -} - -unsigned CompositeAnimation::numberOfActiveAnimations() const -{ - return m_data->numberOfActiveAnimations(); -} - } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.h b/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.h index d51718f..739cfdc 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.h +++ b/src/3rdparty/webkit/WebCore/page/animation/CompositeAnimation.h @@ -31,14 +31,15 @@ #include "AtomicString.h" +#include "ImplicitAnimation.h" +#include "KeyframeAnimation.h" #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> namespace WebCore { -class CompositeAnimationPrivate; +class AnimationControllerPrivate; class AnimationController; -class KeyframeAnimation; class RenderObject; class RenderStyle; @@ -46,7 +47,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)); }; @@ -56,26 +57,24 @@ public: void clearRenderer(); PassRefPtr<RenderStyle> animate(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle); - double willNeedService() const; - - AnimationController* animationController(); + PassRefPtr<RenderStyle> getAnimatedStyle() const; - void setWaitingForStyleAvailable(bool); - bool isWaitingForStyleAvailable() const; + double timeToNextService() const; + + AnimationControllerPrivate* animationController() const { return m_animationController; } void suspendAnimations(); void resumeAnimations(); - bool isSuspended() const; + bool isSuspended() const { return m_isSuspended; } + + bool hasAnimations() const { return !m_transitions.isEmpty() || !m_keyframeAnimations.isEmpty(); } - void styleAvailable(); void setAnimating(bool); bool isAnimatingProperty(int property, bool isRunningNow) const; - PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property); + PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property) const; - - void setAnimationStartTime(double t); - void setTransitionStartTime(int property, double t); + void cleanupFinishedAnimations(); void overrideImplicitAnimations(int property); void resumeOverriddenImplicitAnimations(int property); @@ -85,9 +84,25 @@ public: unsigned numberOfActiveAnimations() const; private: - CompositeAnimation(AnimationController* animationController); + CompositeAnimation(AnimationControllerPrivate* animationController) + : m_animationController(animationController) + , m_numStyleAvailableWaiters(0) + , m_isSuspended(false) + { + } + + void updateTransitions(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle); + void updateKeyframeAnimations(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle); - CompositeAnimationPrivate* m_data; + typedef HashMap<int, RefPtr<ImplicitAnimation> > CSSPropertyTransitionsMap; + typedef HashMap<AtomicStringImpl*, RefPtr<KeyframeAnimation> > AnimationNameMap; + + AnimationControllerPrivate* m_animationController; + CSSPropertyTransitionsMap m_transitions; + AnimationNameMap m_keyframeAnimations; + Vector<AtomicStringImpl*> m_keyframeAnimationOrderMap; + unsigned m_numStyleAvailableWaiters; + bool m_isSuspended; }; } // namespace WebCore diff --git a/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.cpp b/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.cpp index f984909..e93fee4 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.cpp +++ b/src/3rdparty/webkit/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 { @@ -50,17 +52,17 @@ ImplicitAnimation::ImplicitAnimation(const Animation* transition, int animatingP ImplicitAnimation::~ImplicitAnimation() { - // Do the cleanup here instead of in the base class so the specialized methods get called + // // Make sure to tell the renderer that we are ending. This will make sure any accelerated animations are removed. if (!postActive()) - updateStateMachine(AnimationStateInputEndAnimation, -1); + endAnimation(true); } -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,11 +167,11 @@ bool ImplicitAnimation::sendTransitionEvent(const AtomicString& eventType, doubl return false; // Schedule event handling - m_object->animation()->addEventToDispatch(element, eventType, propertyName, elapsedTime); + m_compAnim->animationController()->addEventToDispatch(element, eventType, propertyName, elapsedTime); // Restore the original (unanimated) style if (eventType == eventNames().webkitTransitionEndEvent && element->renderer()) - setChanged(element.get()); + setNeedsStyleRecalc(element.get()); return true; // Did dispatch an event } @@ -137,7 +184,6 @@ void ImplicitAnimation::reset(RenderStyle* to) { ASSERT(to); ASSERT(m_fromStyle); - m_toStyle = to; @@ -170,6 +216,12 @@ bool ImplicitAnimation::isTargetPropertyEqual(int prop, const RenderStyle* targe void ImplicitAnimation::blendPropertyValueInStyle(int prop, RenderStyle* currentStyle) { + // We should never add a transition with a 0 duration and delay. But if we ever did + // it would have a null toStyle. So just in case, let's check that here. (See + // <https://bugs.webkit.org/show_bug.cgi?id=24787> + if (!m_toStyle) + return; + blendProperties(this, prop, currentStyle, m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0)); } @@ -209,4 +261,21 @@ void ImplicitAnimation::validateTransformFunctionList() m_transformFunctionListValid = true; } +double ImplicitAnimation::timeToNextService() +{ + double t = AnimationBase::timeToNextService(); +#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/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.h b/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.h index cf98bba..33fe4e4 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/ImplicitAnimation.h +++ b/src/3rdparty/webkit/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 timeToNextService(); + protected: - bool shouldSendEventForListener(Document::ListenerType); + bool shouldSendEventForListener(Document::ListenerType) const; bool sendTransitionEvent(const AtomicString&, double elapsedTime); void validateTransformFunctionList(); diff --git a/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp b/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp index aae37a7..3f84de1 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp +++ b/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp @@ -29,13 +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 "SystemTime.h" +#include "RenderLayer.h" +#include "RenderLayerBacking.h" +#include <wtf/UnusedParam.h> namespace WebCore { @@ -46,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(); @@ -55,12 +56,50 @@ KeyframeAnimation::KeyframeAnimation(const Animation* animation, RenderObject* r KeyframeAnimation::~KeyframeAnimation() { - // Do the cleanup here instead of in the base class so the specialized methods get called + // Make sure to tell the renderer that we are ending. This will make sure any accelerated animations are removed. if (!postActive()) - updateStateMachine(AnimationStateInputEndAnimation, -1); + endAnimation(true); +} + +void KeyframeAnimation::getKeyframeAnimationInterval(const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& prog) const +{ + // Find the first key + double elapsedTime = getElapsedTime(); + + double t = m_animation->duration() ? (elapsedTime / m_animation->duration()) : 1; + int i = static_cast<int>(t); + t -= i; + if (m_animation->direction() && (i & 1)) + t = 1 - t; + + double scale = 1; + double offset = 0; + Vector<KeyframeValue>::const_iterator endKeyframes = m_keyframes.endKeyframes(); + for (Vector<KeyframeValue>::const_iterator it = m_keyframes.beginKeyframes(); it != endKeyframes; ++it) { + if (t < it->key()) { + // The first key should always be 0, so we should never succeed on the first key + if (!fromStyle) + break; + scale = 1.0 / (it->key() - offset); + toStyle = it->style(); + break; + } + + offset = it->key(); + 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*, const RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle) +void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle) { // Fire the start timeout if needed fireAnimationEventsIfNeeded(); @@ -85,36 +124,12 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render // 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 = (m_startTime > 0 || m_pauseTime > 0) ? ((!paused() ? beginAnimationUpdateTime() : m_pauseTime) - m_startTime) : 0; - if (elapsedTime < 0) - elapsedTime = 0; - - double t = m_animation->duration() ? (elapsedTime / m_animation->duration()) : 1; - int i = static_cast<int>(t); - t -= i; - if (m_animation->direction() && (i & 1)) - t = 1 - t; - + + // Get the from/to styles and progress between const RenderStyle* fromStyle = 0; const RenderStyle* toStyle = 0; - double scale = 1; - double offset = 0; - Vector<KeyframeValue>::const_iterator endKeyframes = m_keyframes.endKeyframes(); - for (Vector<KeyframeValue>::const_iterator it = m_keyframes.beginKeyframes(); it != endKeyframes; ++it) { - if (t < it->key()) { - // The first key should always be 0, so we should never succeed on the first key - if (!fromStyle) - break; - scale = 1.0 / (it->key() - offset); - toStyle = it->style(); - break; - } - - offset = it->key(); - fromStyle = it->style(); - } + double progress; + getKeyframeAnimationInterval(fromStyle, toStyle, progress); // If either style is 0 we have an invalid case, just stop the animation. if (!fromStyle || !toStyle) { @@ -127,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(); @@ -151,14 +189,39 @@ 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 + if (!paused()) + setNeedsStyleRecalc(m_object->node()); + } } -bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType) +bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType) const { return m_object->document()->hasListenerType(listenerType); } @@ -204,11 +267,11 @@ bool KeyframeAnimation::sendAnimationEvent(const AtomicString& eventType, double return false; // Schedule event handling - m_object->animation()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime); + m_compAnim->animationController()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime); // Restore the original (unanimated) style if (eventType == eventNames().webkitAnimationEndEvent && element->renderer()) - setChanged(element.get()); + setNeedsStyleRecalc(element.get()); return true; // Did dispatch an event } @@ -290,4 +353,31 @@ void KeyframeAnimation::validateTransformFunctionList() m_transformFunctionListValid = true; } +double KeyframeAnimation::timeToNextService() +{ + double t = AnimationBase::timeToNextService(); +#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/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.h b/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.h index 5c3176c..4905fc3 100644 --- a/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.h +++ b/src/3rdparty/webkit/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 timeToNextService(); + 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/src/3rdparty/webkit/WebCore/page/qt/FrameQt.cpp b/src/3rdparty/webkit/WebCore/page/qt/FrameQt.cpp index 1bbbff5..388bf66 100644 --- a/src/3rdparty/webkit/WebCore/page/qt/FrameQt.cpp +++ b/src/3rdparty/webkit/WebCore/page/qt/FrameQt.cpp @@ -23,7 +23,7 @@ #include "config.h" #include "Frame.h" -#include "FramePrivate.h" + #include "UserStyleSheetLoader.h" namespace WebCore { @@ -35,18 +35,18 @@ DragImageRef Frame::dragImageForSelection() void Frame::setUserStyleSheetLocation(const KURL& url) { - delete d->m_userStyleSheetLoader; - d->m_userStyleSheetLoader = 0; - if (d->m_doc && d->m_doc->docLoader()) - d->m_userStyleSheetLoader = new UserStyleSheetLoader(d->m_doc, url.string()); + delete m_userStyleSheetLoader; + m_userStyleSheetLoader = 0; + if (m_doc && m_doc->docLoader()) + m_userStyleSheetLoader = new UserStyleSheetLoader(m_doc, url.string()); } void Frame::setUserStyleSheet(const String& styleSheet) { - delete d->m_userStyleSheetLoader; - d->m_userStyleSheetLoader = 0; - if (d->m_doc) - d->m_doc->setUserStyleSheet(styleSheet); + delete m_userStyleSheetLoader; + m_userStyleSheetLoader = 0; + if (m_doc) + m_doc->setUserStyleSheet(styleSheet); } } diff --git a/src/3rdparty/webkit/WebCore/page/win/FrameCGWin.cpp b/src/3rdparty/webkit/WebCore/page/win/FrameCGWin.cpp index da2d8b2..8b0408d 100644 --- a/src/3rdparty/webkit/WebCore/page/win/FrameCGWin.cpp +++ b/src/3rdparty/webkit/WebCore/page/win/FrameCGWin.cpp @@ -28,7 +28,6 @@ #include <windows.h> -#include "FramePrivate.h" #include "FrameView.h" #include "GraphicsContext.h" #include "Settings.h" @@ -101,9 +100,9 @@ HBITMAP Frame::nodeImage(Node* node) const document()->updateLayout(); - d->m_view->setNodeToDraw(node); // invoke special sub-tree drawing mode + m_view->setNodeToDraw(node); // invoke special sub-tree drawing mode HBITMAP result = imageFromRect(this, paintingRect); - d->m_view->setNodeToDraw(0); + m_view->setNodeToDraw(0); return result; } diff --git a/src/3rdparty/webkit/WebCore/page/win/FrameWin.cpp b/src/3rdparty/webkit/WebCore/page/win/FrameWin.cpp index 895d129..0c1c5b1 100644 --- a/src/3rdparty/webkit/WebCore/page/win/FrameWin.cpp +++ b/src/3rdparty/webkit/WebCore/page/win/FrameWin.cpp @@ -30,7 +30,6 @@ #include "TransformationMatrix.h" #include "FloatRect.h" #include "Document.h" -#include "FramePrivate.h" #include "RenderView.h" #include "Settings.h" @@ -62,7 +61,7 @@ void computePageRectsForFrame(Frame* frame, const IntRect& printRect, float head float ratio = static_cast<float>(printRect.height()) / static_cast<float>(printRect.width()); - float pageWidth = static_cast<float>(root->docWidth()); + float pageWidth = static_cast<float>(root->overflowWidth()); float pageHeight = pageWidth * ratio; outPageHeight = static_cast<int>(pageHeight); // this is the height of the page adjusted by margins pageHeight -= (headerHeight + footerHeight); @@ -82,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)); |