diff options
author | Feng Qian <fqian@google.com> | 2009-06-17 12:12:20 -0700 |
---|---|---|
committer | Feng Qian <fqian@google.com> | 2009-06-17 12:12:20 -0700 |
commit | 5f1ab04193ad0130ca8204aadaceae083aca9881 (patch) | |
tree | 5a92cd389e2cfe7fb67197ce14b38469462379f8 /WebCore/page | |
parent | 194315e5a908cc8ed67d597010544803eef1ac59 (diff) | |
download | external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.zip external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.gz external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.bz2 |
Get WebKit r44544.
Diffstat (limited to 'WebCore/page')
102 files changed, 2409 insertions, 11522 deletions
diff --git a/WebCore/page/AXObjectCache.cpp b/WebCore/page/AXObjectCache.cpp deleted file mode 100644 index f8167a5..0000000 --- a/WebCore/page/AXObjectCache.cpp +++ /dev/null @@ -1,256 +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(); - removeAXID(obj); - } -} - -AccessibilityObject* AXObjectCache::get(RenderObject* renderer) -{ - if (!renderer) - return 0; - - AccessibilityObject* obj = 0; - AXID axID = m_renderObjectMapping.get(renderer); - ASSERT(!HashTraits<AXID>::isDeletedValue(axID)); - - if (axID) - obj = m_objects.get(axID).get(); - - return obj; -} - -AccessibilityObject* AXObjectCache::getOrCreate(RenderObject* renderer) -{ - if (!renderer) - return 0; - - AccessibilityObject* obj = get(renderer); - - if (!obj) { - Node* node = renderer->node(); - RefPtr<AccessibilityObject> newObj = 0; - if (renderer->isListBox()) - newObj = AccessibilityListBox::create(renderer); - else if (node && (node->hasTagName(ulTag) || node->hasTagName(olTag) || node->hasTagName(dlTag))) - newObj = AccessibilityList::create(renderer); - else if (renderer->isTable()) - newObj = AccessibilityTable::create(renderer); - else if (renderer->isTableRow()) - newObj = AccessibilityTableRow::create(renderer); - else if (renderer->isTableCell()) - newObj = AccessibilityTableCell::create(renderer); - else - newObj = AccessibilityRenderObject::create(renderer); - - obj = newObj.get(); - - getAXID(obj); - - m_renderObjectMapping.set(renderer, obj->axObjectID()); - m_objects.set(obj->axObjectID(), obj); - attachWrapper(obj); - } - - return obj; -} - -AccessibilityObject* AXObjectCache::getOrCreate(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) -{ - if (!obj) - return; - - 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 = getOrCreate(renderer); - if (obj) - obj->handleActiveDescendantChanged(); -} - -void AXObjectCache::handleAriaRoleChanged(RenderObject* renderer) -{ - if (!renderer) - return; - AccessibilityObject* obj = getOrCreate(renderer); - if (obj && obj->isAccessibilityRenderObject()) - static_cast<AccessibilityRenderObject*>(obj)->setAriaRole(); -} -#endif - -} // namespace WebCore diff --git a/WebCore/page/AXObjectCache.h b/WebCore/page/AXObjectCache.h deleted file mode 100644 index 4fd6dc3..0000000 --- a/WebCore/page/AXObjectCache.h +++ /dev/null @@ -1,116 +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* getOrCreate(RenderObject*); - - // used for objects without backing elements - AccessibilityObject* getOrCreate(AccessibilityRole); - - // will only return the AccessibilityObject if it already exists - AccessibilityObject* get(RenderObject*); - - 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/WebCore/page/AccessibilityImageMapLink.cpp b/WebCore/page/AccessibilityImageMapLink.cpp deleted file mode 100644 index 86ca623..0000000 --- a/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()->getOrCreate(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/WebCore/page/AccessibilityImageMapLink.h b/WebCore/page/AccessibilityImageMapLink.h deleted file mode 100644 index 7fc8d3c..0000000 --- a/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/WebCore/page/AccessibilityList.cpp b/WebCore/page/AccessibilityList.cpp deleted file mode 100644 index 3097b3b..0000000 --- a/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* node = m_renderer->node(); - return node && node->hasTagName(ulTag); -} - -bool AccessibilityList::isOrderedList() const -{ - if (!m_renderer) - return false; - - Node* node = m_renderer->node(); - return node && node->hasTagName(olTag); -} - -bool AccessibilityList::isDefinitionList() const -{ - if (!m_renderer) - return false; - - Node* node = m_renderer->node(); - return node && node->hasTagName(dlTag); -} - - -} // namespace WebCore diff --git a/WebCore/page/AccessibilityList.h b/WebCore/page/AccessibilityList.h deleted file mode 100644 index 315ccac..0000000 --- a/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/WebCore/page/AccessibilityListBox.cpp b/WebCore/page/AccessibilityListBox.cpp deleted file mode 100644 index 37baec9..0000000 --- a/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()->getOrCreate(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* node = m_renderer->node(); - if (!node) - return 0; - - IntRect parentRect = boundingBoxRect(); - - const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(node)->listItems(); - unsigned length = listItems.size(); - for (unsigned i = 0; i < length; i++) { - IntRect rect = static_cast<RenderListBox*>(m_renderer)->itemBoundingBoxRect(parentRect.x(), parentRect.y(), i); - if (rect.contains(point)) - return listBoxOptionAccessibilityObject(listItems[i]); - } - - return axObjectCache()->getOrCreate(m_renderer); -} - -} // namespace WebCore diff --git a/WebCore/page/AccessibilityListBox.h b/WebCore/page/AccessibilityListBox.h deleted file mode 100644 index 3f3352d..0000000 --- a/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/WebCore/page/AccessibilityListBoxOption.cpp b/WebCore/page/AccessibilityListBoxOption.cpp deleted file mode 100644 index 088c556..0000000 --- a/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()->getOrCreate(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()->getOrCreate(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/WebCore/page/AccessibilityListBoxOption.h b/WebCore/page/AccessibilityListBoxOption.h deleted file mode 100644 index 1b588cd..0000000 --- a/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/WebCore/page/AccessibilityObject.cpp b/WebCore/page/AccessibilityObject.cpp deleted file mode 100644 index d5b7ff5..0000000 --- a/WebCore/page/AccessibilityObject.cpp +++ /dev/null @@ -1,1036 +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() -{ -#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; -} - -AccessibilityObject* AccessibilityObject::parentObjectIfExists() const -{ - return 0; -} - -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; -} - -VisibleSelection AccessibilityObject::selection() const -{ - return VisibleSelection(); -} - -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 = VisibleSelection(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.m_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 lastDeepEditingPositionForNode(endRenderer->node()); -} - -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()->getOrCreate(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(nextVisiblePos), endOfLine(nextVisiblePos)).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()->getOrCreate(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; -} - -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; - } -} - -void AccessibilityObject::updateBackingStore() -{ -} - -} // namespace WebCore diff --git a/WebCore/page/AccessibilityObject.h b/WebCore/page/AccessibilityObject.h deleted file mode 100644 index 9141b36..0000000 --- a/WebCore/page/AccessibilityObject.h +++ /dev/null @@ -1,429 +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 VisibleSelection; -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 isInputImage() 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* parentObjectIfExists() 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 VisibleSelection 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 - - // allows for an AccessibilityObject to update its render tree or perform - // other operations update type operations - virtual void updateBackingStore(); - -protected: - unsigned m_id; - AccessibilityChildrenVector m_children; - mutable bool m_haveChildren; - - virtual void clearChildren(); - 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/WebCore/page/AccessibilityRenderObject.cpp b/WebCore/page/AccessibilityRenderObject.cpp deleted file mode 100644 index 8ed352a..0000000 --- a/WebCore/page/AccessibilityRenderObject.cpp +++ /dev/null @@ -1,2476 +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 "RenderInline.h" -#include "RenderListBox.h" -#include "RenderListMarker.h" -#include "RenderMenuList.h" -#include "RenderText.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()->getOrCreate(firstChild); -} - -AccessibilityObject* AccessibilityRenderObject::lastChild() const -{ - if (!m_renderer) - return 0; - - RenderObject* lastChild = m_renderer->lastChild(); - if (!lastChild) - return 0; - - return m_renderer->document()->axObjectCache()->getOrCreate(lastChild); -} - -AccessibilityObject* AccessibilityRenderObject::previousSibling() const -{ - if (!m_renderer) - return 0; - - RenderObject* previousSibling = m_renderer->previousSibling(); - if (!previousSibling) - return 0; - - return m_renderer->document()->axObjectCache()->getOrCreate(previousSibling); -} - -AccessibilityObject* AccessibilityRenderObject::nextSibling() const -{ - if (!m_renderer) - return 0; - - RenderObject* nextSibling = m_renderer->nextSibling(); - if (!nextSibling) - return 0; - - return m_renderer->document()->axObjectCache()->getOrCreate(nextSibling); -} - -AccessibilityObject* AccessibilityRenderObject::parentObjectIfExists() const -{ - if (!m_renderer) - return 0; - - RenderObject *parent = m_renderer->parent(); - if (!parent) - return 0; - - return m_renderer->document()->axObjectCache()->get(parent); -} - -AccessibilityObject* AccessibilityRenderObject::parentObject() const -{ - if (!m_renderer) - return 0; - - RenderObject *parent = m_renderer->parent(); - if (!parent) - return 0; - - if (ariaRoleAttribute() == MenuBarRole) - return m_renderer->document()->axObjectCache()->getOrCreate(parent); - - // menuButton and its corresponding menu are DOM siblings, but Accessibility needs them to be parent/child - if (ariaRoleAttribute() == MenuRole) { - AccessibilityObject* parent = menuButtonForMenu(); - if (parent) - return parent; - } - - return m_renderer->document()->axObjectCache()->getOrCreate(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->isTextControl(); -} - -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 -{ - if (!m_renderer) - return false; - - // Widgets are the replaced elements that we represent to AX as attachments - bool isWidget = m_renderer && m_renderer->isWidget(); - ASSERT(!isWidget || (m_renderer->isReplaced() && !isImage())); - return isWidget && ariaRoleAttribute() == UnknownRole; -} - -bool AccessibilityRenderObject::isPasswordField() const -{ - ASSERT(m_renderer); - if (!m_renderer->node() || !m_renderer->node()->isHTMLElement()) - return false; - if (ariaRoleAttribute() != UnknownRole) - return false; - - InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node())); - if (!inputElement) - return false; - - return inputElement->isPasswordField(); -} - -bool AccessibilityRenderObject::isCheckboxOrRadio() const -{ - AccessibilityRole role = roleValue(); - return role == RadioButtonRole || role == CheckBoxRole; -} - -bool AccessibilityRenderObject::isFileUploadButton() const -{ - if (m_renderer && m_renderer->node() && m_renderer->node()->hasTagName(inputTag)) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->node()); - return input->inputType() == HTMLInputElement::FILE; - } - - return false; -} - -bool AccessibilityRenderObject::isInputImage() const -{ - if (m_renderer && m_renderer->node() && m_renderer->node()->hasTagName(inputTag)) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->node()); - return input->inputType() == HTMLInputElement::IMAGE; - } - - 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); - if (!m_renderer->node() || !m_renderer->node()->isElementNode()) - return false; - - InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node())); - if (!inputElement) - return false; - - return inputElement->isIndeterminate(); -} - -bool AccessibilityRenderObject::isChecked() const -{ - ASSERT(m_renderer); - if (!m_renderer->node() || !m_renderer->node()->isElementNode()) - return false; - - InputElement* inputElement = toInputElement(static_cast<Element*>(m_renderer->node())); - if (!inputElement) - return false; - - return inputElement->isChecked(); -} - -bool AccessibilityRenderObject::isHovered() const -{ - 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->node() && static_cast<HTMLSelectElement*>(m_renderer->node())->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()->getOrCreate(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->node(); - return node && ((node->isElementNode() && static_cast<Element*>(node)->isFormControlElement()) - || 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->node(); - 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->node(); currRenderer = currRenderer->parent()) { - if (currRenderer->isRenderBlock()) { - RenderInline* continuation = toRenderBlock(currRenderer)->inlineContinuation(); - if (continuation) - return cache->getOrCreate(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->getOrCreate(node->renderer())->isAnchor())) - return static_cast<Element*>(node); - } - - return 0; -} - -Element* AccessibilityRenderObject::actionElement() const -{ - if (!m_renderer) - return 0; - - Node* node = m_renderer->node(); - if (node) { - if (node->hasTagName(inputTag)) { - HTMLInputElement* input = static_cast<HTMLInputElement*>(node); - if (!input->disabled() && (isCheckboxOrRadio() || input->isTextButton())) - return input; - } else if (node->hasTagName(buttonTag)) - return static_cast<Element*>(node); - } - - if (isFileUploadButton()) - return static_cast<Element*>(m_renderer->node()); - - if (AccessibilityObject::isARIAInput(ariaRoleAttribute())) - return static_cast<Element*>(m_renderer->node()); - - if (isImageButton()) - return static_cast<Element*>(m_renderer->node()); - - 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->node(); - if (!node) - return 0; - if (!node->isElementNode()) - return 0; - - // FIXME: Do the continuation search like anchorElement does - for (Element* element = static_cast<Element*>(node); element; element = element->parentElement()) { - if (element->inlineEventListenerForType(eventNames().clickEvent) || element->inlineEventListenerForType(eventNames().mousedownEvent) || element->inlineEventListenerForType(eventNames().mouseupEvent)) - return element; - } - - return 0; -} - -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()->getOrCreate(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()->getOrCreate(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->node() && curr->node()->isHTMLElement()) { - const AtomicString& summary = static_cast<Element*>(curr->node())->getAttribute(summaryAttr); - if (!summary.isEmpty()) - return summary; - const AtomicString& title = static_cast<Element*>(curr->node())->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->node(); - 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->node() && isCheckboxOrRadio()) - return true; - - return false; -} - -int AccessibilityRenderObject::intValue() const -{ - if (!m_renderer || isPasswordField()) - return 0; - - if (isHeading()) - return headingLevel(m_renderer->node()); - - Node* node = m_renderer->node(); - 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->node(); 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->node(); - 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 && !titleUIElement()) - 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() || isInputImage()) { - Node* node = m_renderer->node(); - if (node && node->isHTMLElement()) { - const AtomicString& alt = static_cast<HTMLElement*>(node)->getAttribute(altAttr); - if (alt.isEmpty()) - return String(); - return alt; - } - } - - 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->node()) // If we are a continuation, we want to make sure to use the primary renderer. - obj = obj->node()->renderer(); - - // FIXME: This doesn't work correctly with transforms. - Vector<IntRect> rects; - 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->node())); - if (!label || !label->renderer()) - return boundingBoxRect(); - - IntRect labelRect = axObjectCache()->getOrCreate(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()->getOrCreate(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()->getOrCreate(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()->getOrCreate(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()->getOrCreate(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()->getOrCreate(static_cast<RenderFieldset*>(m_renderer)->findLegend()); - - // checkbox and radio hide their labels. Only controls get titleUIElements for now - if (isCheckboxOrRadio() || !isControl()) - return 0; - - Node* element = m_renderer->node(); - HTMLLabelElement* label = labelForElement(static_cast<Element*>(element)); - if (label && label->renderer()) - return axObjectCache()->getOrCreate(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()->getOrCreate(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() || !toRenderText(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->node(); - if (node && node->hasTagName(labelTag)) - return false; - - if (m_renderer->isBlockFlow() && m_renderer->childrenInline()) - return !toRenderBlock(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 - RenderImage* image = toRenderImage(m_renderer); - if (image->height() <= 1 || image->width() <= 1) - return true; - - // check whether rendered image was stretched from one-dimensional file image - if (isNativeImage()) { - 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 toRenderView(m_renderer)->frameView()->layoutCount(); -} - -String AccessibilityRenderObject::text() const -{ - if (!isTextControl() || isPasswordField()) - return String(); - - if (isNativeTextControl()) - return toRenderTextControl(m_renderer)->text(); - - Node* node = m_renderer->node(); - 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->node(); - if (!node) - return 0; - - RefPtr<Range> currentSelectionRange = selection().toNormalizedRange(); - 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 = toRenderTextControl(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->node(); - if (!node) - return nullAtom; - if (!node->isElementNode()) - return nullAtom; - return static_cast<Element*>(node)->getAttribute(accesskeyAttr); -} - -VisibleSelection 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 = toRenderTextControl(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 = toRenderTextControl(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->node(); - frame->selection()->setSelection(VisibleSelection(Position(node, range.start), - Position(node, range.start + range.length), DOWNSTREAM)); -} - -KURL AccessibilityRenderObject::url() const -{ - if (isAnchor() && m_renderer->node()->hasTagName(aTag)) { - if (HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(anchorElement())) - return anchor->href(); - } - - if (isWebArea()) - return m_renderer->document()->url(); - - if (isImage() && m_renderer->node() && m_renderer->node()->hasTagName(imgTag)) - return static_cast<HTMLImageElement*>(m_renderer->node())->src(); - - if (isInputImage()) - return static_cast<HTMLInputElement*>(m_renderer->node())->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->node() || - (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->node()->isElementNode()) - static_cast<Element*>(m_renderer->node())->focus(); - else - m_renderer->document()->setFocusedNode(m_renderer->node()); - } -} - -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->node()); - input->setValue(string); - } else if (m_renderer->isTextArea()) { - HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(m_renderer->node()); - textArea->setValue(string); - } -} - -bool AccessibilityRenderObject::isEnabled() const -{ - ASSERT(m_renderer); - if (!m_renderer->node() || !m_renderer->node()->isElementNode()) - return true; - - FormControlElement* formControlElement = toFormControlElement(static_cast<Element*>(m_renderer->node())); - if (!formControlElement) - return true; - - return formControlElement->isEnabled(); -} - -RenderView* AccessibilityRenderObject::topRenderer() const -{ - return m_renderer->document()->topDocument()->renderView(); -} - -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()->getOrCreate(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()->getOrCreate(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()->getOrCreate(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->node(); - if (!node) - return VisiblePositionRange(); - - VisiblePosition startPos = firstDeepEditingPositionForNode(node); - VisiblePosition endPos = lastDeepEditingPositionForNode(node); - - // the VisiblePositions are equal for nodes like buttons, so adjust for that - // FIXME: Really? [button, 0] and [button, 1] are distinct (before and after the button) - // I expect this code is only hit for things like empty divs? In which case I don't think - // the behavior is correct here -- eseidel - if (startPos == endPos) { - endPos = endPos.next(); - if (endPos.isNull()) - endPos = startPos; - } - - return VisiblePositionRange(startPos, endPos); -} - -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(VisibleSelection(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 toRenderTextControl(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 toRenderTextControl(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.m_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 { - VisibleSelection newSelection = VisibleSelection(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(); - RenderView* renderView = 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(HitTestRequest::ReadOnly | - HitTestRequest::Active); - HitTestResult result(ourpoint); - renderView->layer()->hitTest(request, result); - innerNode = result.innerNode(); - if (!innerNode || !innerNode->renderer()) - return VisiblePosition(); - - pointResult = result.localPoint(); - - // done if hit something other than a widget - RenderObject* 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; - renderView = frame->document()->renderView(); - 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->node(); 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(VisibleSelection(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 || !m_renderer->hasLayer()) - return 0; - - RenderLayer* layer = toRenderBox(m_renderer)->layer(); - - HitTestRequest request(HitTestRequest::ReadOnly | - HitTestRequest::Active); - 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()->getOrCreate(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()->getOrCreate(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()->node() && !renderer()->node()->isElementNode()) - return 0; - Element* element = static_cast<Element*>(renderer()->node()); - - 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()->getOrCreate(target->renderer()); - if (obj->isAccessibilityRenderObject()) - // an activedescendant is only useful if it has a renderer, because that's what's needed to post the notification - return obj; - return 0; -} - - -void AccessibilityRenderObject::handleActiveDescendantChanged() -{ - Element* element = static_cast<Element*>(renderer()->node()); - 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->node(); renderer = renderer->parent()) { - if (renderer->isTextControl()) - return renderer->document()->axObjectCache()->getOrCreate(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->node(); - 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->node()) != 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 -{ - ASSERT(m_renderer); - - // NOTE: It would be more accurate to ask the document whether setFocusedNode() would - // do anything. For example, it setFocusedNode() will do nothing if the current focused - // node will not relinquish the focus. - if (!m_renderer->node() || !m_renderer->node()->isElementNode()) - return false; - - FormControlElement* formControlElement = toFormControlElement(static_cast<Element*>(m_renderer->node())); - if (formControlElement && !formControlElement->isEnabled()) - return false; - - switch (roleValue()) { - case WebCoreLinkRole: - case ImageMapLinkRole: - 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() -{ - // this method is meant as a quick way of marking dirty - // a portion of the accessibility tree - - markChildrenDirty(); - - // This object may not be accessible (and thus may not appear - // in the hierarchy), which means we need to go up the parent - // chain and mark the parent's dirty. Ideally, we would want - // to only access the next object that is not ignored, but - // asking an element if it's ignored can lead to an examination of the - // render tree which is dangerous. - // Only parents that already exist must be retrieved, otherwise objects can be created - // at bad times - for (AccessibilityObject* parent = parentObjectIfExists(); parent; parent = parent->parentObjectIfExists()) { - if (parent->isAccessibilityRenderObject()) - static_cast<AccessibilityRenderObject *>(parent)->markChildrenDirty(); - } -} - -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_childrenDirty) { - clearChildren(); - m_childrenDirty = false; - } - - 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 = toRenderImage(m_renderer)->imageMap(); - if (map) { - for (Node* current = map->firstChild(); current; current = current->traverseNextNode(map)) { - - // add an <area> element for this child if it has a link - if (current->isLink()) { - AccessibilityImageMapLink* areaObject = static_cast<AccessibilityImageMapLink*>(m_renderer->document()->axObjectCache()->getOrCreate(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()->node()); - 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->node()); - if (childElement && childElement->isElementNode()) { // do this check to ensure safety of static_cast above - String selectedAttrString = childElement->getAttribute("aria-selected").string(); - if (equalIgnoringCase(selectedAttrString, "true")) { - 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); -} - -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; - } -} - -void AccessibilityRenderObject::updateBackingStore() -{ - if (!m_renderer) - return; - m_renderer->view()->layoutIfNeeded(); -} - -} // namespace WebCore diff --git a/WebCore/page/AccessibilityRenderObject.h b/WebCore/page/AccessibilityRenderObject.h deleted file mode 100644 index 5370eac..0000000 --- a/WebCore/page/AccessibilityRenderObject.h +++ /dev/null @@ -1,243 +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 RenderView; -class VisibleSelection; -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 isInputImage() 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* parentObjectIfExists() 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; } - RenderView* topRenderer() const; - RenderTextControl* textControl() const; - Document* document() const; - FrameView* topDocumentFrameView() const; - HTMLLabelElement* labelElementContainer() const; - - virtual KURL url() const; - virtual PlainTextRange selectedTextRange() const; - virtual VisibleSelection 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; - - virtual void updateBackingStore(); - -protected: - RenderObject* m_renderer; - AccessibilityRole m_ariaRole; - mutable bool m_childrenDirty; - - void setRenderObject(RenderObject* renderer) { m_renderer = renderer; } - - 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; - - void markChildrenDirty() const { m_childrenDirty = true; } -}; - -} // namespace WebCore - -#endif // AccessibilityRenderObject_h diff --git a/WebCore/page/AccessibilityTable.cpp b/WebCore/page/AccessibilityTable.cpp deleted file mode 100644 index 2b60d43..0000000 --- a/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) -{ -#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) - 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->node(); - 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->node(); - 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->getOrCreate(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->getOrCreate(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()->getOrCreate(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) { - - unsigned numRows = tableSection->numRows(); - unsigned numCols = tableSection->numColumns(); - - rowCount += numRows; - - unsigned sectionSpecificRow = row - rowOffset; - if (row < rowCount && column < numCols && sectionSpecificRow < numRows) { - cell = tableSection->cellAt(sectionSpecificRow, column).cell; - - // we didn't find the cell, which means there's spanning happening - // 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 += numRows; - // we didn't find anything between the rows we should have - if (row < rowCount) - break; - tableSection = table->sectionBelow(tableSection, true); - } - - if (!cell) - return 0; - - AccessibilityObject* cellObject = axObjectCache()->getOrCreate(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->node(); - 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/WebCore/page/AccessibilityTable.h b/WebCore/page/AccessibilityTable.h deleted file mode 100644 index b98b6b7..0000000 --- a/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/WebCore/page/AccessibilityTableCell.cpp b/WebCore/page/AccessibilityTableCell.cpp deleted file mode 100644 index f7cbe98..0000000 --- a/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()->getOrCreate(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->node(); - if (!cellElement || !cellElement->hasTagName(thTag)) - return 0; - - return axObjectCache()->getOrCreate(headerCell); -} - -} // namespace WebCore diff --git a/WebCore/page/AccessibilityTableCell.h b/WebCore/page/AccessibilityTableCell.h deleted file mode 100644 index 8f8dd77..0000000 --- a/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/WebCore/page/AccessibilityTableColumn.cpp b/WebCore/page/AccessibilityTableColumn.cpp deleted file mode 100644 index ff330c0..0000000 --- a/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->node(); - if (!node) - continue; - - if (thTagRequired && !node->hasTagName(thTag)) - continue; - - cell = testCell; - } - - if (!cell) - return 0; - - return m_parentTable->axObjectCache()->getOrCreate(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/WebCore/page/AccessibilityTableColumn.h b/WebCore/page/AccessibilityTableColumn.h deleted file mode 100644 index 6270398..0000000 --- a/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/WebCore/page/AccessibilityTableHeaderContainer.cpp b/WebCore/page/AccessibilityTableHeaderContainer.cpp deleted file mode 100644 index af9de39..0000000 --- a/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/WebCore/page/AccessibilityTableHeaderContainer.h b/WebCore/page/AccessibilityTableHeaderContainer.h deleted file mode 100644 index 8a9448a..0000000 --- a/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/WebCore/page/AccessibilityTableRow.cpp b/WebCore/page/AccessibilityTableRow.cpp deleted file mode 100644 index e67fcfe..0000000 --- a/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()->getOrCreate(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->node(); - if (!cellNode || !cellNode->hasTagName(thTag)) - return 0; - - return cell; -} - -} // namespace WebCore diff --git a/WebCore/page/AccessibilityTableRow.h b/WebCore/page/AccessibilityTableRow.h deleted file mode 100644 index 0ec7f04..0000000 --- a/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/WebCore/page/BarInfo.cpp b/WebCore/page/BarInfo.cpp index 153aee0..f6a1210 100644 --- a/WebCore/page/BarInfo.cpp +++ b/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/WebCore/page/BarInfo.h b/WebCore/page/BarInfo.h index 4cbbcfc..376b8fc 100644 --- a/WebCore/page/BarInfo.h +++ b/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/WebCore/page/Chrome.cpp b/WebCore/page/Chrome.cpp index b37ebc4..86de82e 100644 --- a/WebCore/page/Chrome.cpp +++ b/WebCore/page/Chrome.cpp @@ -35,7 +35,7 @@ #include "HitTestResult.h" #include "InspectorController.h" #include "Page.h" -#include "PageGroup.h" +#include "PageGroupLoadDeferrer.h" #include "ResourceHandle.h" #include "ScriptController.h" #include "SecurityOrigin.h" @@ -54,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) @@ -152,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; } @@ -378,16 +371,6 @@ void Chrome::print(Frame* frame) m_client->print(frame); } -void Chrome::disableSuddenTermination() -{ - m_client->disableSuddenTermination(); -} - -void Chrome::enableSuddenTermination() -{ - m_client->enableSuddenTermination(); -} - void Chrome::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation) { // Defer loads in case the client method runs a new event loop that would @@ -402,6 +385,12 @@ 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) @@ -434,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) @@ -454,45 +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()) - 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/WebCore/page/Chrome.h b/WebCore/page/Chrome.h index ab0b42f..c26e450 100644 --- a/WebCore/page/Chrome.h +++ b/WebCore/page/Chrome.h @@ -20,6 +20,7 @@ #ifndef Chrome_h #define Chrome_h +#include "Cursor.h" #include "FileChooser.h" #include "FocusDirection.h" #include "HostWindow.h" @@ -117,13 +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/WebCore/page/ChromeClient.h b/WebCore/page/ChromeClient.h index 7b0fa76..e155754 100644 --- a/WebCore/page/ChromeClient.h +++ b/WebCore/page/ChromeClient.h @@ -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) @@ -43,6 +47,7 @@ namespace WebCore { class FloatRect; class Frame; class Geolocation; + class HTMLParserQuirks; class HitTestResult; class IntRect; class Node; @@ -98,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; @@ -121,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; @@ -146,9 +151,6 @@ 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, @@ -157,20 +159,27 @@ namespace WebCore { // This is an asynchronous call. The ChromeClient can display UI asking the user for permission // to use Geolococation. The ChromeClient must call Geolocation::setShouldClearCache() appropriately. - virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*) { } + virtual void 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*) { } + 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() { } + 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) diff --git a/WebCore/page/Console.cpp b/WebCore/page/Console.cpp index 33128ea..99a0fc8 100644 --- a/WebCore/page/Console.cpp +++ b/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; @@ -151,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); @@ -176,7 +181,7 @@ void Console::addMessage(MessageLevel level, ScriptCallStack* callStack, bool ac String message; if (getFirstArgumentAsString(callStack->state(), lastCaller, message)) - page->chrome()->client()->addMessageToConsole(message, lastCaller.lineNumber(), lastCaller.sourceURL().prettyURL()); + page->chrome()->client()->addMessageToConsole(JSMessageSource, level, message, lastCaller.lineNumber(), lastCaller.sourceURL().prettyURL()); page->inspectorController()->addMessageToConsole(JSMessageSource, level, callStack); @@ -264,7 +269,7 @@ void Console::count(ScriptCallStack* callStack) 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) { diff --git a/WebCore/page/Console.h b/WebCore/page/Console.h index 2a24a2a..79396ea 100644 --- a/WebCore/page/Console.h +++ b/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 @@ -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/WebCore/page/Console.idl b/WebCore/page/Console.idl index fb7688d..4803508 100644 --- a/WebCore/page/Console.idl +++ b/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/WebCore/page/ContextMenuController.cpp b/WebCore/page/ContextMenuController.cpp index 522e939..58e6519 100644 --- a/WebCore/page/ContextMenuController.cpp +++ b/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" @@ -212,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, 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: @@ -293,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/WebCore/page/Coordinates.h b/WebCore/page/Coordinates.h index 743b04d..acb5dd0 100644 --- a/WebCore/page/Coordinates.h +++ b/WebCore/page/Coordinates.h @@ -36,7 +36,7 @@ typedef int ExceptionCode; class Coordinates : public RefCounted<Coordinates> { public: - static PassRefPtr<Coordinates> create(double latitude, double longitude, double altitude, double accuracy, double altitudeAccuracy, double heading, double speed) { return adoptRef(new Coordinates(latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed)); } + 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; } @@ -46,10 +46,15 @@ public: 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, double altitude, double accuracy, double altitudeAccuracy, double heading, double speed) + 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) @@ -57,6 +62,10 @@ private: , m_altitudeAccuracy(altitudeAccuracy) , m_heading(heading) , m_speed(speed) + , m_canProvideAltitude(providesAltitude) + , m_canProvideAltitudeAccuracy(providesAltitudeAccuracy) + , m_canProvideHeading(providesHeading) + , m_canProvideSpeed(providesSpeed) { } @@ -67,6 +76,11 @@ private: double m_altitudeAccuracy; double m_heading; double m_speed; + + bool m_canProvideAltitude; + bool m_canProvideAltitudeAccuracy; + bool m_canProvideHeading; + bool m_canProvideSpeed; }; } // namespace WebCore diff --git a/WebCore/page/Coordinates.idl b/WebCore/page/Coordinates.idl index 6318212..f6c82b5 100644 --- a/WebCore/page/Coordinates.idl +++ b/WebCore/page/Coordinates.idl @@ -28,13 +28,13 @@ module core { interface Coordinates { readonly attribute double latitude; readonly attribute double longitude; - readonly attribute double altitude; + readonly attribute [Custom] double altitude; readonly attribute double accuracy; - readonly attribute double altitudeAccuracy; - readonly attribute double heading; - readonly attribute double speed; + readonly attribute [Custom] double altitudeAccuracy; + readonly attribute [Custom] double heading; + readonly attribute [Custom] double speed; -#if defined(LANGUAGE_JAVASCRIPT) +#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT [DontEnum] DOMString toString(); #endif }; diff --git a/WebCore/page/DOMSelection.cpp b/WebCore/page/DOMSelection.cpp index 86fe911..3b54f02 100644 --- a/WebCore/page/DOMSelection.cpp +++ b/WebCore/page/DOMSelection.cpp @@ -95,7 +95,7 @@ int DOMSelection::anchorOffset() const { if (!m_frame) return 0; - return anchorPosition(visibleSelection()).m_offset; + return anchorPosition(visibleSelection()).deprecatedEditingOffset(); } Node* DOMSelection::focusNode() const @@ -109,7 +109,7 @@ int DOMSelection::focusOffset() const { if (!m_frame) return 0; - return focusPosition(visibleSelection()).m_offset; + return focusPosition(visibleSelection()).deprecatedEditingOffset(); } Node* DOMSelection::baseNode() const @@ -123,7 +123,7 @@ int DOMSelection::baseOffset() const { if (!m_frame) return 0; - return basePosition(visibleSelection()).m_offset; + return basePosition(visibleSelection()).deprecatedEditingOffset(); } @@ -138,7 +138,7 @@ int DOMSelection::extentOffset() const { if (!m_frame) return 0; - return extentPosition(visibleSelection()).m_offset; + return extentPosition(visibleSelection()).deprecatedEditingOffset(); } bool DOMSelection::isCollapsed() const diff --git a/WebCore/page/DOMSelection.idl b/WebCore/page/DOMSelection.idl index a54f9e4..be6c2b4 100644 --- a/WebCore/page/DOMSelection.idl +++ b/WebCore/page/DOMSelection.idl @@ -58,7 +58,7 @@ module window { void removeAllRanges(); void addRange(in Range range); -#if defined(LANGUAGE_JAVASCRIPT) +#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT [DontEnum] DOMString toString(); #endif diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp index f6fde05..b4f3dee 100644 --- a/WebCore/page/DOMWindow.cpp +++ b/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" @@ -57,6 +60,7 @@ #include "Screen.h" #include "SecurityOrigin.h" #include "Settings.h" +#include "SuddenTermination.h" #include "WebKitPoint.h" #include <algorithm> #include <wtf/MathExtras.h> @@ -104,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 @@ -144,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) { @@ -153,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() @@ -335,6 +549,9 @@ Storage* DOMWindow::sessionStorage() const Storage* DOMWindow::localStorage() const { + if (m_localStorage) + return m_localStorage.get(); + Document* document = this->document(); if (!document) return 0; @@ -414,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() @@ -497,7 +715,7 @@ void DOMWindow::alert(const String& message) if (!m_frame) return; - m_frame->document()->updateRendering(); + m_frame->document()->updateStyleIfNeeded(); Page* page = m_frame->page(); if (!page) @@ -511,7 +729,7 @@ bool DOMWindow::confirm(const String& message) if (!m_frame) return false; - m_frame->document()->updateRendering(); + m_frame->document()->updateStyleIfNeeded(); Page* page = m_frame->page(); if (!page) @@ -525,7 +743,7 @@ String DOMWindow::prompt(const String& message, const String& defaultValue) if (!m_frame) return String(); - m_frame->document()->updateRendering(); + m_frame->document()->updateStyleIfNeeded(); Page* page = m_frame->page(); if (!page) @@ -766,9 +984,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(); } @@ -952,351 +1176,873 @@ 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. } #if ENABLE(TOUCH_EVENTS) // Android EventListener* DOMWindow::ontouchstart() const { - return inlineEventListenerForType(eventNames().touchstartEvent); + return getAttributeEventListener(eventNames().touchstartEvent); } void DOMWindow::setOntouchstart(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().touchstartEvent, eventListener); + setAttributeEventListener(eventNames().touchstartEvent, eventListener); } EventListener* DOMWindow::ontouchend() const { - return inlineEventListenerForType(eventNames().touchendEvent); + return getAttributeEventListener(eventNames().touchendEvent); } void DOMWindow::setOntouchend(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().touchendEvent, eventListener); + setAttributeEventListener(eventNames().touchendEvent, eventListener); } EventListener* DOMWindow::ontouchmove() const { - return inlineEventListenerForType(eventNames().touchmoveEvent); + return getAttributeEventListener(eventNames().touchmoveEvent); } void DOMWindow::setOntouchmove(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().touchmoveEvent, eventListener); + setAttributeEventListener(eventNames().touchmoveEvent, eventListener); } EventListener* DOMWindow::ontouchcancel() const { - return inlineEventListenerForType(eventNames().touchcancelEvent); + return getAttributeEventListener(eventNames().touchcancelEvent); } void DOMWindow::setOntouchcancel(PassRefPtr<EventListener> eventListener) { - setInlineEventListenerForType(eventNames().touchcancelEvent, eventListener); + setAttributeEventListener(eventNames().touchcancelEvent, eventListener); } #endif diff --git a/WebCore/page/DOMWindow.h b/WebCore/page/DOMWindow.h index b779cbd..7d97445 100644 --- a/WebCore/page/DOMWindow.h +++ b/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,10 +54,11 @@ namespace WebCore { class Location; class MessagePort; class Navigator; + class Node; class PostMessageTimer; + class ScheduledAction; class Screen; class WebKitPoint; - class Node; #if ENABLE(DOM_STORAGE) class SessionStorage; @@ -66,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(); @@ -82,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; @@ -198,6 +216,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; @@ -208,6 +254,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; @@ -232,6 +292,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; @@ -242,6 +306,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; @@ -267,6 +333,56 @@ namespace WebCore { void setOntouchcancel(PassRefPtr<EventListener>); #endif + 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. Screen* optionalScreen() const { return m_screen.get(); } @@ -283,17 +399,22 @@ namespace WebCore { Location* optionalLocation() const { return m_location.get(); } #if ENABLE(DOM_STORAGE) Storage* optionalSessionStorage() const { return m_sessionStorage.get(); } - Storage* optionalLocalStorage() const { return m_sessionStorage.get(); } + Storage* optionalLocalStorage() const { return m_localStorage.get(); } #endif #if ENABLE(OFFLINE_WEB_APPLICATIONS) 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; @@ -318,8 +439,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/WebCore/page/DOMWindow.idl b/WebCore/page/DOMWindow.idl index fd0cd55..612ae42 100644 --- a/WebCore/page/DOMWindow.idl +++ b/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, V8DisallowShadowing] 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, @@ -113,7 +125,7 @@ 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 @@ -143,14 +155,14 @@ module window { 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 @@ -163,12 +175,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) @@ -177,46 +190,91 @@ 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; #if ENABLE_TOUCH_EVENTS - attribute [ProtectedListener] EventListener ontouchstart; - attribute [ProtectedListener] EventListener ontouchend; - attribute [ProtectedListener] EventListener ontouchmove; - attribute [ProtectedListener] EventListener ontouchcancel; + attribute EventListener ontouchstart; + attribute EventListener ontouchend; + attribute EventListener ontouchmove; + attribute EventListener ontouchcancel; #endif -#if defined(V8_BINDING) - attribute [ProtectedListener] EventListener ondragdrop; - attribute [ProtectedListener] EventListener onmove; -#endif + 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, @@ -225,9 +283,13 @@ module window { [Custom] void removeEventListener(in DOMString type, in EventListener listener, in boolean useCapture); - // FIXME: Implement dispatchEvent + boolean dispatchEvent(in Event evt) + raises(EventException); + + [V8Custom=DOMWindowNOP] void captureEvents(/*in long eventFlags*/); + [V8Custom=DOMWindowNOP] void releaseEvents(/*in long eventFlags*/); -#if defined(LANGUAGE_JAVASCRIPT) +#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT // Global constructors attribute StyleSheetConstructor StyleSheet; attribute CSSStyleSheetConstructor CSSStyleSheet; @@ -347,6 +409,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; @@ -370,9 +435,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; @@ -390,21 +455,22 @@ 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(V8_BINDING) - // With JSC, these are added in JSDOMWindowBase.cpp. - attribute XMLHttpRequestConstructor XMLHttpRequest; - attribute MessageChannelConstructor MessageChannel; - attribute WebKitPointConstructor WebKitPoint; -#if ENABLE_XSLT - attribute XSLTProcessorConstructor XSLTProcessor; + +#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 ENABLE_WORKERS - attribute WorkerConstructor Worker; + +#if defined(ENABLE_WORKERS) && ENABLE_WORKERS + attribute [JSCCustomGetter] WorkerConstructor Worker; // Usable with the new operator #endif - attribute WebKitCSSMatrixConstructor WebKitCSSMatrix; -#endif // V8_BINDING attribute PluginConstructor Plugin; attribute PluginArrayConstructor PluginArray; @@ -415,25 +481,24 @@ module window { attribute ClientRectConstructor ClientRect; attribute ClientRectListConstructor ClientRectList; -#if ENABLE_DOM_STORAGE +#if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE attribute StorageConstructor Storage; attribute StorageEventConstructor StorageEvent; #endif -#if ENABLE_VIDEO - attribute HTMLAudioElementConstructor HTMLAudioElement; - attribute HTMLMediaElementConstructor HTMLMediaElement; - attribute HTMLVideoElementConstructor HTMLVideoElement; - attribute MediaErrorConstructor MediaError; -#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; @@ -450,9 +515,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; @@ -462,28 +526,14 @@ module window { // attribute SVGFEMorphologyElementConstructor SVGFEMorphologyElement; attribute SVGFETurbulenceElementConstructor SVGFETurbulenceElement; #endif +#endif #endif // defined(LANGUAGE_JAVASCRIPT) -#if defined(V8_BINDING) - // These were implemented in JSCDOMWindowBase and not moved to IDL yet. - - [Custom] DOMWindow open(in DOMString url, - in DOMString name, - in [Optional] DOMString options); - - [Custom] DOMObject showModalDialog(in DOMString url, - in [Optional] DOMObject dialogArgs, - in [Optional] DOMString featureArgs); - - // These are defined on JSDOMWindowBase, but not implemented. - [Custom=DOMWindowNOP] void captureEvents(in long eventFlags); - [Custom=DOMWindowNOP] void releaseEvents(in long eventFlags); - - // window.toString requires special handling - [V8DoNotCheckSignature, DoNotCheckDomainSecurity, Custom, DontEnum] DOMString toString(); +#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/WebCore/page/DragController.cpp b/WebCore/page/DragController.cpp index cba109a..e1b5ea7 100644 --- a/WebCore/page/DragController.cpp +++ b/WebCore/page/DragController.cpp @@ -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) { } @@ -128,9 +128,10 @@ static PassRefPtr<DocumentFragment> documentFragmentFromDragData(DragData* dragD 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(); @@ -154,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) { @@ -173,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); @@ -185,16 +185,16 @@ 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) && concludeEditDrag(dragData)) { - m_document = 0; + m_documentUnderMouse = 0; return true; } - m_document = 0; + m_documentUnderMouse = 0; if (operationForLoad(dragData) == DragOperationNone) return false; @@ -203,27 +203,30 @@ bool DragController::performDrag(DragData* dragData) 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)) @@ -257,7 +260,7 @@ DragOperation DragController::tryDocumentDrag(DragData* dragData, DragDestinatio { ASSERT(dragData); - if (!m_document) + if (!m_documentUnderMouse) return DragOperationNone; DragOperation operation = DragOperationNone; @@ -265,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; @@ -275,17 +278,14 @@ 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)) { - VisibleSelection dragCaret; - if (Frame* frame = m_document->frame()) - dragCaret = frame->visiblePositionForPoint(point); + VisibleSelection dragCaret = m_documentUnderMouse->frame()->visiblePositionForPoint(point); m_page->dragCaretController()->setSelection(dragCaret); } - + + Frame* innerFrame = element->document()->frame(); return dragIsMove(innerFrame->selection()) ? DragOperationMove : DragOperationCopy; } @@ -302,8 +302,7 @@ 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); @@ -325,11 +324,11 @@ bool DragController::concludeEditDrag(DragData* dragData) ASSERT(dragData); ASSERT(!m_isHandlingDrag); - 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); @@ -341,7 +340,7 @@ bool DragController::concludeEditDrag(DragData* dragData) if (!innerFrame) return false; RefPtr<Range> innerRange = innerFrame->selection()->toNormalizedRange(); - RefPtr<CSSStyleDeclaration> style = m_document->createCSSStyleDeclaration(); + RefPtr<CSSStyleDeclaration> style = m_documentUnderMouse->createCSSStyleDeclaration(); ExceptionCode ec; style->setProperty("color", color.name(), ec); if (!innerFrame->editor()->shouldApplyStyle(style.get(), innerRange.get())) @@ -357,8 +356,7 @@ bool DragController::concludeEditDrag(DragData* dragData) } if (HTMLInputElement* fileInput = asFileInput(element)) { - - if (!fileInput->isEnabled()) + if (!fileInput->isEnabledFormControl()) return false; if (!dragData->containsFiles()) @@ -407,7 +405,7 @@ bool DragController::concludeEditDrag(DragData* dragData) 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(); @@ -418,7 +416,7 @@ bool DragController::concludeEditDrag(DragData* dragData) 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); @@ -449,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; @@ -458,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 @@ -606,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); @@ -756,17 +754,10 @@ 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; @@ -775,4 +766,4 @@ void DragController::placeDragCaret(const IntPoint& windowPoint) m_page->dragCaretController()->setSelection(dragCaret); } -} +} // namespace WebCore diff --git a/WebCore/page/DragController.h b/WebCore/page/DragController.h index 3beff5a..6fe1f7f 100644 --- a/WebCore/page/DragController.h +++ b/WebCore/page/DragController.h @@ -64,8 +64,7 @@ namespace WebCore { 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; } @@ -74,7 +73,7 @@ namespace WebCore { 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); @@ -104,6 +103,8 @@ namespace WebCore { 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&); @@ -113,17 +114,16 @@ namespace WebCore { Page* m_page; DragClient* m_client; - Document* m_document; // The document the mouse was last dragged over. + 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/WebCore/page/EditorClient.h b/WebCore/page/EditorClient.h index 67462c5..cdf0bd8 100644 --- a/WebCore/page/EditorClient.h +++ b/WebCore/page/EditorClient.h @@ -61,11 +61,22 @@ 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 { - int resultType; // 1 for spelling, 2 for grammar + TextCheckingType type; int location; int length; Vector<GrammarDetail> details; + String replacement; }; class EditorClient { @@ -133,12 +144,32 @@ 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 checkSpellingAndGrammarOfParagraph(const UChar* text, int length, bool checkGrammar, Vector<TextCheckingResult>& results) = 0; + 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; @@ -151,3 +182,4 @@ public: } #endif // EditorClient_h + diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp index 7e79792..1031a3d 100644 --- a/WebCore/page/EventHandler.cpp +++ b/WebCore/page/EventHandler.cpp @@ -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" @@ -58,12 +58,13 @@ #include "PlatformWheelEvent.h" #include "RenderFrameSet.h" #include "RenderTextControlSingleLine.h" -#include "RenderWidget.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) @@ -122,6 +123,20 @@ static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDir 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) @@ -144,8 +159,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) @@ -293,10 +306,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())); @@ -312,8 +327,7 @@ 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.m_offset, start.node(), start.m_offset); - if (before <= 0) + if (comparePositions(pos, start) <= 0) newSelection = VisibleSelection(pos, end); else newSelection = VisibleSelection(start, pos); @@ -437,8 +451,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; @@ -446,9 +462,13 @@ bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const allowDHTMLDrag(DHTMLFlag, UAFlag); if (!DHTMLFlag && !UAFlag) return false; - + + FrameView* view = m_frame->view(); + if (!view) + return false; + HitTestRequest request(HitTestRequest::ReadOnly); - HitTestResult result(m_frame->view()->windowToContents(event.pos())); + 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); @@ -557,15 +577,18 @@ 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()) { + && 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 = VisibleSelection(pos); } @@ -593,10 +616,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 @@ -619,9 +646,11 @@ void EventHandler::autoscrollTimerFired(Timer<EventHandler>*) 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(); @@ -631,8 +660,13 @@ void EventHandler::autoscrollTimerFired(Timer<EventHandler>*) } #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; @@ -643,25 +677,26 @@ 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 @@ -690,13 +725,21 @@ void EventHandler::setAutoscrollRenderer(RenderObject* renderer) void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const { - if (!m_frame) { - 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)); } @@ -733,11 +776,17 @@ HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool all // 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, ignoreClipping); + 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) @@ -767,8 +816,10 @@ void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed) 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 @@ -778,9 +829,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; } @@ -920,10 +976,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(); @@ -1001,6 +1060,14 @@ 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) { @@ -1013,11 +1080,19 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) 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; HitTestRequest request(HitTestRequest::Active); - MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent); + // 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(); @@ -1026,11 +1101,13 @@ 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); @@ -1045,12 +1122,13 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) } #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(); @@ -1072,15 +1150,17 @@ 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); @@ -1090,10 +1170,8 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) // in case the scrollbar widget was destroyed when the mouse event was handled. if (mev.scrollbar()) { const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMouse.get(); - HitTestRequest request(HitTestRequest::ReadOnly | - HitTestRequest::Active); - mev = prepareMouseEvent(request, 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; } @@ -1108,12 +1186,12 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent) // 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)) { - HitTestRequest request(HitTestRequest::ReadOnly | - HitTestRequest::Active); - mev = prepareMouseEvent(request, mouseEvent); + 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)) @@ -1226,8 +1304,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(); @@ -1258,8 +1336,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; @@ -1334,17 +1416,22 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent) bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTarget, const PlatformMouseEvent& event, Clipboard* clipboard) { - m_frame->view()->resetDeferredRepaintDelay(); + 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()); - IntPoint contentsPos = m_frame->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; + ExceptionCode ec; dragTarget->dispatchEvent(me.get(), ec); return me->defaultPrevented(); } @@ -1445,8 +1532,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) @@ -1545,7 +1631,8 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targetNode, bool /*cancelable*/, int clickCount, const PlatformMouseEvent& mouseEvent, bool setUnder) { - m_frame->view()->resetDeferredRepaintDelay(); + if (FrameView* view = m_frame->view()) + view->resetDeferredRepaintDelay(); updateMouseEventTargetNode(targetNode, mouseEvent, setUnder); @@ -1582,14 +1669,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; + } } } @@ -1606,7 +1696,10 @@ bool EventHandler::handleWheelEvent(PlatformWheelEvent& e) 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(HitTestRequest::ReadOnly); HitTestResult result(vPoint); @@ -1644,9 +1737,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(); } @@ -1699,7 +1797,7 @@ bool EventHandler::canMouseDownStartSelect(Node* node) for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) { if (Node* node = curr->node()) - return node->dispatchEventForType(eventNames().selectstartEvent, true, true); + return node->dispatchEvent(eventNames().selectstartEvent, true, true); } return true; @@ -1712,7 +1810,7 @@ bool EventHandler::canMouseDragExtendSelect(Node* node) for (RenderObject* curr = node->renderer(); curr; curr = curr->parent()) { if (Node* node = curr->node()) - return node->dispatchEventForType(eventNames().selectstartEvent, true, true); + return node->dispatchEvent(eventNames().selectstartEvent, true, true); } return true; @@ -1737,10 +1835,12 @@ void EventHandler::hoverTimerFired(Timer<EventHandler>*) ASSERT(m_frame->document()); if (RenderView* renderer = m_frame->contentRenderer()) { - HitTestRequest request(HitTestRequest::MouseMove); - HitTestResult result(m_frame->view()->windowToContents(m_currentMousePosition)); - renderer->layer()->hitTest(request, result); - m_frame->document()->updateRendering(); + 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(); + } } } @@ -1783,14 +1883,17 @@ 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 @@ -1799,8 +1902,9 @@ bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent) RefPtr<Node> node = eventTargetNodeForDocument(m_frame->document()); if (!node) return false; - - m_frame->view()->resetDeferredRepaintDelay(); + + if (FrameView* view = m_frame->view()) + view->resetDeferredRepaintDelay(); // FIXME: what is this doing here, in keyboard event handler? m_frame->loader()->resetMultipleFormSubmissionProtection(); @@ -1887,21 +1991,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(); } } @@ -1936,7 +2041,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; @@ -1960,7 +2068,8 @@ bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const { 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) @@ -2049,7 +2158,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; @@ -2099,7 +2209,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 @@ -2136,7 +2247,8 @@ bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEve if (!target) return false; - m_frame->view()->resetDeferredRepaintDelay(); + if (FrameView* view = m_frame->view()) + view->resetDeferredRepaintDelay(); RefPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text); event->setUnderlyingEvent(underlyingEvent); @@ -2247,33 +2359,6 @@ void EventHandler::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; -} - void EventHandler::sendResizeEvent() { m_frame->document()->dispatchWindowEvent(eventNames().resizeEvent, false, false); @@ -2285,34 +2370,7 @@ void EventHandler::sendScrollEvent() if (!v) return; v->setWasScrolledByUser(true); - m_frame->document()->dispatchEventForType(eventNames().scrollEvent, true, false); -} - -unsigned EventHandler::pendingFrameBeforeUnloadEventCount() -{ - return m_pendingFrameBeforeUnloadEventCount; -} - -void EventHandler::addPendingFrameBeforeUnloadEventCount() -{ - m_pendingFrameBeforeUnloadEventCount += 1; - m_frame->page()->changePendingBeforeUnloadEventCount(1); - return; -} - -void EventHandler::removePendingFrameBeforeUnloadEventCount() -{ - 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; + m_frame->document()->dispatchEvent(eventNames().scrollEvent, true, false); } bool EventHandler::passMousePressEventToScrollbar(MouseEventWithHitTestResults& mev, Scrollbar* scrollbar) diff --git a/WebCore/page/EventHandler.h b/WebCore/page/EventHandler.h index 0a59eb3..0ad70c2 100644 --- a/WebCore/page/EventHandler.h +++ b/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,22 +27,15 @@ #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 { @@ -51,7 +44,6 @@ class Clipboard; class Cursor; class Event; class FloatPoint; -class FloatRect; class Frame; class HitTestRequest; class HitTestResult; @@ -68,7 +60,6 @@ class Scrollbar; class String; class SVGElementInstance; class TextEvent; -class VisiblePosition; class Widget; #if ENABLE(TOUCH_EVENTS) // Android class PlatformTouchEvent; @@ -164,33 +155,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 *); - void sendFakeEventsAfterWidgetTracking(NSEvent* initiatingEvent); + bool sendContextMenuEvent(NSEvent *); + bool eventMayStartDrag(NSEvent *); + + void sendFakeEventsAfterWidgetTracking(NSEvent *initiatingEvent); void setActivationEventNumber(int num) { m_activationEventNumber = num; } - NSEvent *currentNSEvent(); + static NSEvent *currentNSEvent(); #endif private: @@ -210,8 +195,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&); @@ -283,14 +268,8 @@ 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; @@ -298,6 +277,12 @@ private: bool capturesDragging() const { return m_capturesDragging; } +#if PLATFORM(MAC) && defined(__OBJC__) + NSView *mouseDownViewIfStillGood(); + + PlatformMouseEvent currentPlatformMouseEvent() const; +#endif + Frame* m_frame; bool m_mousePressed; @@ -321,6 +306,7 @@ private: bool m_autoscrollInProgress; bool m_mouseDownMayStartAutoscroll; bool m_mouseDownWasInSubframe; + #if ENABLE(SVG) bool m_svgPan; RefPtr<SVGElementInstance> m_instanceUnderMouse; @@ -352,16 +338,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/WebCore/page/FocusController.cpp b/WebCore/page/FocusController.cpp index 9760b3c..8dad846 100644 --- a/WebCore/page/FocusController.cpp +++ b/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() @@ -114,9 +121,16 @@ bool FocusController::advanceFocus(FocusDirection direction, KeyboardEvent* even ASSERT(frame); Document* document = frame->document(); + 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) { @@ -195,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; } @@ -223,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; @@ -248,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; @@ -296,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/WebCore/page/Frame.cpp b/WebCore/page/Frame.cpp index 1caae9a..eedf09b 100644 --- a/WebCore/page/Frame.cpp +++ b/WebCore/page/Frame.cpp @@ -31,6 +31,7 @@ #include "ApplyStyleCommand.h" #include "BeforeUnloadEvent.h" #include "CSSComputedStyleDeclaration.h" +#include "CSSMutableStyleDeclaration.h" #include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CachedCSSStyleSheet.h" @@ -70,6 +71,7 @@ #include "TextResourceDecoder.h" #include "XMLNames.h" #include "ScriptController.h" +#include "htmlediting.h" #include "npruntime_impl.h" #include "visible_units.h" #include <wtf/RefCountedLeakCounter.h> @@ -176,7 +178,6 @@ 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 @@ -187,9 +188,6 @@ Frame::~Frame() frameCounter.decrement(); #endif - if (m_script.haveWindowShell()) - m_script.windowShell()->disconnectFrame(); - disconnectOwnerElement(); if (m_domWindow) @@ -226,7 +224,7 @@ FrameView* Frame::view() const 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 @@ -573,9 +571,18 @@ static bool isFrameElement(const Node *n) void Frame::setFocusedNodeIfNeeded() { - if (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(); @@ -596,6 +603,9 @@ void Frame::setFocusedNodeIfNeeded() } document()->setFocusedNode(0); } + + if (caretBrowsing) + page()->focusController()->setFocusedNode(0, this); } void Frame::selectionLayoutChanged() @@ -603,8 +613,9 @@ void Frame::selectionLayoutChanged() bool caretRectChanged = selection()->recomputeCaretRect(); #if ENABLE(TEXT_CARET) + bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); bool shouldBlink = m_caretVisible - && selection()->isCaret() && selection()->isContentEditable(); + && 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. @@ -652,7 +663,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.m_offset, endRenderer, endPos.m_offset); + view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset()); } } } @@ -764,6 +775,7 @@ void Frame::setPrinting(bool printing, float minPageWidth, float maxPageWidth, b void Frame::setJSStatusBarText(const String& text) { + 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); @@ -771,6 +783,7 @@ void Frame::setJSStatusBarText(const String& text) void Frame::setJSDefaultStatusBarText(const String& text) { + 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); @@ -1193,7 +1206,7 @@ void Frame::selectionTextRects(Vector<FloatRect>& rects, bool clipToVisibleConte RefPtr<Range> selectedRange = selection()->toNormalizedRange(); Vector<IntRect> intRects; - selectedRange->addLineBoxRects(intRects, true); + selectedRange->textRects(intRects, true); unsigned size = intRects.size(); FloatRect visibleContentRect = m_view->visibleContentRect(); @@ -1289,8 +1302,6 @@ void Frame::clearTimers(FrameView *view, Document *document) if (view) { view->unscheduleRelayout(); if (view->frame()) { - if (document && document->renderer() && document->renderer()->hasLayer()) - document->renderView()->layer()->suspendMarquees(); view->frame()->animation()->suspendAnimations(document); view->frame()->eventHandler()->stopAutoscrollTimer(); } @@ -1341,7 +1352,8 @@ 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 (!selection()->isNone() || !isContentEditable()) + bool caretBrowsing = settings() && settings()->caretBrowsingEnabled(); + if (!selection()->isNone() || !(isContentEditable() || caretBrowsing)) return; Node* node = doc->documentElement(); @@ -1567,13 +1579,7 @@ void Frame::pageDestroyed() if (page() && page()->focusController()->focusedFrame() == this) page()->focusController()->setFocusedFrame(0); -#if USE(JSC) script()->clearWindowShell(); -#endif - - // This will stop any JS timers - if (script()->haveWindowShell()) - script()->windowShell()->disconnectFrame(); script()->clearScriptObjects(); script()->updatePlatformScriptObjects(); @@ -1623,20 +1629,21 @@ 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; + 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->defaultEventHandler(beforeUnloadEvent.get()); @@ -1665,7 +1672,8 @@ void Frame::respondToChangedSelection(const VisibleSelection& oldSelection, bool if (isContinuousSpellCheckingEnabled) { VisibleSelection newAdjacentWords; VisibleSelection newSelectedSentence; - if (selection()->selection().isContentEditable()) { + 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) @@ -1748,20 +1756,18 @@ void Frame::createView(const IntSize& viewportSize, setView(0); - FrameView* frameView; + RefPtr<FrameView> frameView; if (isMainFrame) { - frameView = new FrameView(this, viewportSize); + frameView = FrameView::create(this, viewportSize); frameView->setFixedLayoutSize(fixedLayoutSize); frameView->setUseFixedLayout(useFixedLayout); } else - frameView = new FrameView(this); + frameView = FrameView::create(this); frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode); frameView->updateDefaultScrollbarState(); setView(frameView); - // FrameViews are created with a ref count of 1. Release this ref since we've assigned it to frame. - frameView->deref(); if (backgroundColor.isValid()) frameView->updateBackgroundRecursively(backgroundColor, transparent); @@ -1770,7 +1776,7 @@ void Frame::createView(const IntSize& viewportSize, frameView->setParentVisible(true); if (ownerRenderer()) - ownerRenderer()->setWidget(frameView); + ownerRenderer()->setWidget(frameView.get()); if (HTMLFrameOwnerElement* owner = ownerElement()) view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff); diff --git a/WebCore/page/Frame.h b/WebCore/page/Frame.h index 5d46acd..acd91e5 100644 --- a/WebCore/page/Frame.h +++ b/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> * @@ -91,7 +91,7 @@ public: { return adoptRef(new Frame(page, ownerElement, client)); } - void setView(FrameView*); + void setView(PassRefPtr<FrameView>); ~Frame(); void init(); @@ -193,7 +193,7 @@ public: public: void focusWindow(); void unfocusWindow(); - bool shouldClose(); + bool shouldClose(RegisteredEventListenerVector* alternateEventListeners = 0); void scheduleClose(); void setJSStatusBarText(const String&); diff --git a/WebCore/page/FrameTree.cpp b/WebCore/page/FrameTree.cpp index adb5c90..24f125d 100644 --- a/WebCore/page/FrameTree.cpp +++ b/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> diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp index 5f1ee65..f753447 100644 --- a/WebCore/page/FrameView.cpp +++ b/WebCore/page/FrameView.cpp @@ -94,8 +94,7 @@ struct ScheduledEvent { }; FrameView::FrameView(Frame* frame) - : m_refCount(1) - , m_frame(frame) + : m_frame(frame) , m_vmode(ScrollbarAuto) , m_hmode(ScrollbarAuto) , m_slowRepaintObjectCount(0) @@ -113,35 +112,26 @@ FrameView::FrameView(Frame* frame) , 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) - , 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) +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() @@ -156,7 +146,6 @@ FrameView::~FrameView() setHasHorizontalScrollbar(false); // Remove native scrollbars now before we lose the connection to the HostWindow. setHasVerticalScrollbar(false); - ASSERT(m_refCount == 0); ASSERT(m_scheduledEvents.isEmpty()); ASSERT(!m_enqueueEvents); @@ -171,6 +160,8 @@ FrameView::~FrameView() void FrameView::reset() { m_useSlowRepaints = false; + m_isOverlapped = false; + m_contentIsOpaque = false; m_borderX = 30; m_borderY = 30; m_layoutTimer.stop(); @@ -197,6 +188,7 @@ void FrameView::reset() m_isPainting = false; m_isVisuallyNonEmpty = false; m_firstVisuallyNonEmptyLayoutCallbackPending = true; + m_lockedToAnchor = false; } bool FrameView::isFrameView() const @@ -319,12 +311,12 @@ PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientatio Document* doc = m_frame->document(); // Try the <body> element first as a scrollbar source. - Element* body = doc->body(); + 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(); + Element* docElement = doc ? doc->documentElement() : 0; if (docElement && docElement->renderer() && docElement->renderer()->style()->hasPseudoStyle(SCROLLBAR)) return RenderScrollbar::createCustomScrollbar(this, orientation, docElement->renderBox()); @@ -339,6 +331,8 @@ PassRefPtr<Scrollbar> FrameView::createScrollbar(ScrollbarOrientation orientatio void FrameView::setContentsSize(const IntSize& size) { + m_deferSetNeedsLayouts++; + ScrollView::setContentsSize(size); Page* page = frame() ? frame()->page() : 0; @@ -346,6 +340,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() @@ -443,6 +442,7 @@ void FrameView::layout(bool allowSubtree) m_layoutTimer.stop(); m_delayedLayout = false; + m_setNeedsLayoutWasDeferred = false; // Protect the view from being deleted during layout (in recalcStyle) RefPtr<FrameView> protector(this); @@ -491,7 +491,7 @@ 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 = m_layoutRoot; @@ -614,7 +614,7 @@ void FrameView::layout(bool allowSubtree) #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(); @@ -649,6 +649,9 @@ void FrameView::layout(bool allowSubtree) ASSERT(m_enqueueEvents); } + if (lockedToAnchor()) + m_frame->loader()->gotoAnchor(); + m_nestedLayoutCount--; } @@ -684,7 +687,7 @@ String FrameView::mediaType() const bool FrameView::useSlowRepaints() const { - return m_useSlowRepaints || m_slowRepaintObjectCount > 0; + return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || m_isOverlapped || !m_contentIsOpaque; } void FrameView::setUseSlowRepaints() @@ -705,7 +708,25 @@ void FrameView::removeSlowRepaintObject() ASSERT(m_slowRepaintObjectCount > 0); m_slowRepaintObjectCount--; if (!m_slowRepaintObjectCount) - setCanBlitOnScroll(!m_useSlowRepaints); + 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() @@ -717,6 +738,7 @@ void FrameView::scrollRectIntoViewRecursively(const IntRect& r) { bool wasInProgrammaticScroll = m_inProgrammaticScroll; m_inProgrammaticScroll = true; + setLockedToAnchor(false); ScrollView::scrollRectIntoViewRecursively(r); m_inProgrammaticScroll = wasInProgrammaticScroll; } @@ -725,6 +747,7 @@ void FrameView::setScrollPosition(const IntPoint& scrollPoint) { bool wasInProgrammaticScroll = m_inProgrammaticScroll; m_inProgrammaticScroll = true; + setLockedToAnchor(false); ScrollView::setScrollPosition(scrollPoint); m_inProgrammaticScroll = wasInProgrammaticScroll; } @@ -857,8 +880,11 @@ void FrameView::updateDeferredRepaintDelay() void FrameView::resetDeferredRepaintDelay() { m_deferredRepaintDelay = 0; - if (m_deferredRepaintTimer.isActive()) - m_deferredRepaintTimer.startOneShot(0); + if (m_deferredRepaintTimer.isActive()) { + m_deferredRepaintTimer.stop(); + if (!m_deferringRepaints) + doDeferredRepaints(); + } } double FrameView::adjustedDeferredRepaintDelay() const @@ -990,12 +1016,17 @@ bool FrameView::needsLayout() const return layoutPending() || (root && root->needsLayout()) || m_layoutRoot - || document->hasChangedChild() // can occur when using WebKit ObjC interface - || m_frame->needsReapplyStyles(); + || (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); @@ -1320,6 +1351,7 @@ void FrameView::setWasScrolledByUser(bool wasScrolledByUser) { if (m_inProgrammaticScroll) return; + setLockedToAnchor(false); m_wasScrolledByUser = wasScrolledByUser; } @@ -1360,6 +1392,9 @@ void FrameView::paintContents(GraphicsContext* p, const IntRect& rect) } ASSERT(!needsLayout()); + if (needsLayout()) + return; + ASSERT(!m_isPainting); m_isPainting = true; @@ -1417,6 +1452,13 @@ 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::forceLayout(bool allowSubtree) @@ -1466,7 +1508,7 @@ void FrameView::adjustPageHeight(float *newBottom, float oldTop, float oldBottom // 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)); + IntRect dirtyRect(0, (int)floorf(oldTop), root->overflowWidth(), (int)ceilf(oldBottom - oldTop)); root->layer()->paint(&context, dirtyRect); *newBottom = root->bestTruncatedAt(); if (*newBottom == 0) diff --git a/WebCore/page/FrameView.h b/WebCore/page/FrameView.h index 07295d3..16eadc5 100644 --- a/WebCore/page/FrameView.h +++ b/WebCore/page/FrameView.h @@ -48,12 +48,12 @@ 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); @@ -143,6 +139,8 @@ public: void setMediaType(const String&); void setUseSlowRepaints(); + void setIsOverlapped(bool); + void setContentIsOpaque(bool); void addSlowRepaintObject(); void removeSlowRepaintObject(); @@ -186,13 +184,19 @@ public: 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); @@ -204,8 +208,12 @@ 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(); @@ -215,7 +223,6 @@ private: 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; @@ -226,6 +233,8 @@ private: ScrollbarMode m_vmode; ScrollbarMode m_hmode; bool m_useSlowRepaints; + bool m_isOverlapped; + bool m_contentIsOpaque; unsigned m_slowRepaintObjectCount; int m_borderX, m_borderY; @@ -270,12 +279,17 @@ private: 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 diff --git a/WebCore/page/Geolocation.cpp b/WebCore/page/Geolocation.cpp index e2f31a1..8abe8a6 100644 --- a/WebCore/page/Geolocation.cpp +++ b/WebCore/page/Geolocation.cpp @@ -34,13 +34,18 @@ 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>*) @@ -71,11 +76,11 @@ void Geolocation::disconnectFrame() 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()); @@ -86,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()); @@ -129,9 +134,10 @@ void Geolocation::setIsAllowed(bool allowed) { m_allowGeolocation = allowed ? Yes : No; - if (isAllowed()) + if (isAllowed()) { + startTimers(); geolocationServicePositionChanged(m_service.get()); - else { + } else { WTF::RefPtr<WebCore::PositionError> error = WebCore::PositionError::create(PositionError::PERMISSION_DENIED, "User disallowed GeoLocation"); handleError(error.get()); } @@ -205,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); diff --git a/WebCore/page/Geolocation.h b/WebCore/page/Geolocation.h index a14fc4b..ae24bdd 100644 --- a/WebCore/page/Geolocation.h +++ b/WebCore/page/Geolocation.h @@ -38,6 +38,7 @@ #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> +#include <wtf/Vector.h> namespace WebCore { @@ -54,8 +55,8 @@ 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(); @@ -72,16 +73,18 @@ private: 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(); } @@ -91,6 +94,11 @@ private: void sendPositionToOneShots(Geoposition*); void sendPositionToWatchers(Geoposition*); + static void startTimer(Vector<RefPtr<GeoNotifier> >&); + void startTimersForOneShots(); + void startTimersForWatchers(); + void startTimers(); + void handleError(PositionError*); void requestPermission(); diff --git a/WebCore/page/Geoposition.idl b/WebCore/page/Geoposition.idl index 2bcd40d..de508fe 100644 --- a/WebCore/page/Geoposition.idl +++ b/WebCore/page/Geoposition.idl @@ -29,7 +29,7 @@ module core { 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/WebCore/page/History.idl b/WebCore/page/History.idl index c8cddae..fa308fb 100644 --- a/WebCore/page/History.idl +++ b/WebCore/page/History.idl @@ -26,7 +26,7 @@ module window { interface [ -#if defined(V8_BINDING) +#if defined(V8_BINDING) && V8_BINDING CheckDomainSecurity, #endif CustomGetOwnPropertySlot, diff --git a/WebCore/page/Location.cpp b/WebCore/page/Location.cpp index ba28086..c8780eb 100644 --- a/WebCore/page/Location.cpp +++ b/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 diff --git a/WebCore/page/Location.idl b/WebCore/page/Location.idl index 20f8bbd..e7fa31a 100644 --- a/WebCore/page/Location.idl +++ b/WebCore/page/Location.idl @@ -29,13 +29,16 @@ module window { interface [ -#if defined(V8_BINDING) +#if defined(V8_BINDING) && V8_BINDING CheckDomainSecurity, #endif CustomGetOwnPropertySlot, CustomPutFunction, CustomDeleteProperty, - CustomGetPropertyNames + CustomGetPropertyNames, + CustomDefineGetter, + CustomPrototypePutFunction, + CustomPrototypeDefineGetter ] Location { attribute [DoNotCheckDomainSecurityOnSet, CustomSetter, V8DisallowShadowing] DOMString href; @@ -52,10 +55,10 @@ module window { attribute [CustomSetter] DOMString search; attribute [CustomSetter] DOMString hash; -#if defined(LANGUAGE_JAVASCRIPT) +#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT [DontEnum, Custom, V8OnInstance, V8ReadOnly] DOMString toString(); #endif -#if defined(V8_BINDING) +#if defined(V8_BINDING) && V8_BINDING [DontEnum, Custom, V8OnInstance, V8ReadOnly] DOMObject valueOf(); #endif }; diff --git a/WebCore/page/Navigator.cpp b/WebCore/page/Navigator.cpp index dd4d27d..3603b86 100644 --- a/WebCore/page/Navigator.cpp +++ b/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) diff --git a/WebCore/page/Navigator.idl b/WebCore/page/Navigator.idl index 905159c..8048ff3 100644 --- a/WebCore/page/Navigator.idl +++ b/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/WebCore/page/Page.cpp b/WebCore/page/Page.cpp index 6456bf0..70b4459 100644 --- a/WebCore/page/Page.cpp +++ b/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,17 +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 the document does not have a body the event should be dispatched to the document - Node* 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) @@ -120,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) { @@ -211,8 +202,8 @@ void Page::goToItem(HistoryItem* item, FrameLoadType type) { // Abort any current load if we're going to a history item - // Define what to do with any open database connections. By default we stop them and terminate the database thread. - DatabasePolicy databasePolicy = DatabasePolicyStop; + // 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. @@ -571,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() @@ -652,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/WebCore/page/Page.h b/WebCore/page/Page.h index f140783..eedd24c 100644 --- a/WebCore/page/Page.h +++ b/WebCore/page/Page.h @@ -159,11 +159,6 @@ namespace WebCore { 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*); @@ -200,6 +195,9 @@ namespace WebCore { void setMemoryCacheClientCallsEnabled(bool); bool areMemoryCacheClientCallsEnabled() const { return m_areMemoryCacheClientCallsEnabled; } + void setJavaScriptURLsAreAllowed(bool); + bool javaScriptURLsAreAllowed() const; + private: void initGroup(); @@ -231,7 +229,9 @@ namespace WebCore { bool m_cookieEnabled; bool m_areMemoryCacheClientCallsEnabled; float m_mediaVolume; - + + bool m_javaScriptURLsAreAllowed; + InspectorController* m_parentInspectorController; String m_userStyleSheetPath; @@ -243,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/WebCore/page/PageGroupLoadDeferrer.cpp b/WebCore/page/PageGroupLoadDeferrer.cpp new file mode 100644 index 0000000..f274de3 --- /dev/null +++ b/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/WebCore/page/qt/AccessibilityObjectQt.cpp b/WebCore/page/PageGroupLoadDeferrer.h index 1710027..1bdb45c 100644 --- a/WebCore/page/qt/AccessibilityObjectQt.cpp +++ b/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/WebCore/page/PrintContext.cpp b/WebCore/page/PrintContext.cpp index b83d714..2202559 100644 --- a/WebCore/page/PrintContext.cpp +++ b/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; diff --git a/WebCore/page/Screen.cpp b/WebCore/page/Screen.cpp index 396a6f4..d2bb60f 100644 --- a/WebCore/page/Screen.cpp +++ b/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/WebCore/page/Screen.h b/WebCore/page/Screen.h index a740ccb..6f34195 100644 --- a/WebCore/page/Screen.h +++ b/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/WebCore/page/SecurityOrigin.cpp b/WebCore/page/SecurityOrigin.cpp index a1863c9..187ec31 100644 --- a/WebCore/page/SecurityOrigin.cpp +++ b/WebCore/page/SecurityOrigin.cpp @@ -246,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 @@ -277,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/WebCore/page/Settings.cpp b/WebCore/page/Settings.cpp index f55ac42..b67cf44 100644 --- a/WebCore/page/Settings.cpp +++ b/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) @@ -65,9 +67,11 @@ Settings::Settings(Page* page) #ifdef ANDROID_BLOCK_NETWORK_IMAGE , m_blockNetworkImage(false) #endif + , 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) @@ -100,8 +104,17 @@ Settings::Settings(Page* page) , m_zoomsTextOnly(false) , m_enforceCSSMIMETypeInStrictMode(true) , m_usesEncodingDetector(false) - , m_maximumDecodedImageSize(std::numeric_limits<size_t>::max()) , 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. @@ -546,4 +559,14 @@ 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/WebCore/page/Settings.h b/WebCore/page/Settings.h index 5a9ee3a..f2f4279 100644 --- a/WebCore/page/Settings.h +++ b/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*); @@ -119,7 +134,7 @@ namespace WebCore { 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; } @@ -135,7 +150,10 @@ 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; } @@ -255,6 +273,12 @@ namespace WebCore { 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; @@ -308,9 +332,11 @@ namespace WebCore { #ifdef ANDROID_BLOCK_NETWORK_IMAGE bool m_blockNetworkImage : 1; #endif + 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; @@ -343,8 +369,9 @@ namespace WebCore { bool m_zoomsTextOnly : 1; bool m_enforceCSSMIMETypeInStrictMode : 1; bool m_usesEncodingDetector : 1; - size_t m_maximumDecodedImageSize; bool m_allowScriptsToCloseWindows : 1; + unsigned m_editingBehavior : 1; + bool m_downloadableBinaryFontsEnabled : 1; #if USE(SAFARI_THEME) static bool gShouldPaintNativeControls; diff --git a/WebCore/page/android/InspectorControllerAndroid.cpp b/WebCore/page/android/InspectorControllerAndroid.cpp index c480e94..922c743 100644 --- a/WebCore/page/android/InspectorControllerAndroid.cpp +++ b/WebCore/page/android/InspectorControllerAndroid.cpp @@ -27,6 +27,7 @@ #include "InspectorController.h" #include "InspectorClient.h" +#include "InspectorFrontend.h" #include "Frame.h" #include "Node.h" @@ -65,7 +66,6 @@ struct InspectorDatabaseResource : public RefCounted<InspectorDatabaseResource> }; InspectorController::InspectorController(Page*, InspectorClient* client) - : m_startProfiling(this, 0) { m_client = client; } @@ -90,16 +90,8 @@ void InspectorController::didOpenDatabase(Database*, String const&, String const bool InspectorController::enabled() const { return false; } void InspectorController::inspect(Node*) {} bool InspectorController::windowVisible() { return false; } -#if USE(JSC) -void InspectorController::addProfile(PassRefPtr<JSC::Profile>, unsigned int, const JSC::UString&) {} -void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const JSC::UString& sourceString) {} -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::scriptImported(unsigned long identifier, const JSC::UString& sourceString) {} -#elif USE(V8) -void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const String& sourceString) {} +void InspectorController::resourceRetrievedByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString) {} void InspectorController::scriptImported(unsigned long identifier, const String& sourceString) {} -#endif void InspectorController::inspectedPageDestroyed() {} void InspectorController::inspectedWindowScriptObjectCleared(Frame* frame) {} @@ -116,5 +108,4 @@ void InspectorController::handleMousePressOnNode(Node*) {} void InspectorController::didPause() {} #endif -void InspectorController::startUserInitiatedProfiling(Timer<InspectorController>*) {} } // namespace WebCore diff --git a/WebCore/page/animation/AnimationBase.cpp b/WebCore/page/animation/AnimationBase.cpp index e500fe4..7b8a189 100644 --- a/WebCore/page/animation/AnimationBase.cpp +++ b/WebCore/page/animation/AnimationBase.cpp @@ -101,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), @@ -413,7 +419,16 @@ static void ensurePropertyMap() gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingTop, &RenderStyle::paddingTop, &RenderStyle::setPaddingTop)); gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingBottom, &RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom)); 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)); @@ -469,20 +484,13 @@ static void ensurePropertyMap() // TODO: // - // CSSPropertyBackground, CSSPropertyBackgroundPosition // CSSPropertyMinWidth, CSSPropertyMaxWidth, CSSPropertyMinHeight, CSSPropertyMaxHeight // CSSPropertyTextIndent // CSSPropertyVerticalAlign - // CSSPropertyWebkitBackgroundOrigin - // CSSPropertyWebkitBackgroundSize - // CSSPropertyWebkitMaskPosition - // CSSPropertyWebkitMaskOrigin - // CSSPropertyWebkitMaskSize // // Compound properties that have components that should be animatable: // // CSSPropertyWebkitColumns - // CSSPropertyWebkitMask // CSSPropertyWebkitBoxReflect // Make sure unused slots have a value @@ -516,7 +524,10 @@ static void addPropertyWrapper(int propertyID, PropertyWrapperBase* wrapper) static void addShorthandProperties() { static const int animatableShorthandProperties[] = { - CSSPropertyBackground, // for background-color + CSSPropertyBackground, // for background-color, background-position + CSSPropertyBackgroundPosition, + CSSPropertyWebkitMask, // for mask-position + CSSPropertyWebkitMaskPosition, CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft, CSSPropertyBorderColor, CSSPropertyBorderWidth, @@ -581,8 +592,8 @@ AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer AnimationBase::~AnimationBase() { - m_compAnim->removeFromStyleAvailableWaitList(this); - m_compAnim->removeFromStartTimeResponseWaitList(this); + m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); + m_compAnim->animationController()->removeFromStartTimeResponseWaitList(this); } bool AnimationBase::propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b) @@ -649,11 +660,11 @@ bool AnimationBase::animationOfPropertyIsAccelerated(int prop) } #endif -void AnimationBase::setChanged(Node* node) +void AnimationBase::setNeedsStyleRecalc(Node* node) { ASSERT(!node || (node->document() && !node->document()->inPageCache())); if (node) - node->setChanged(AnimationStyleChange); + node->setNeedsStyleRecalc(AnimationStyleChange); } double AnimationBase::duration() const @@ -676,7 +687,7 @@ 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->removeFromStyleAvailableWaitList(this); + m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); m_animState = AnimationStateNew; m_startTime = 0; m_pauseTime = -1; @@ -688,7 +699,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) if (input == AnimationStateInputRestartAnimation) { if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->removeFromStyleAvailableWaitList(this); + m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); m_animState = AnimationStateNew; m_startTime = 0; m_pauseTime = -1; @@ -703,7 +714,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) if (input == AnimationStateInputEndAnimation) { if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->removeFromStyleAvailableWaitList(this); + m_compAnim->animationController()->removeFromStyleAvailableWaitList(this); m_animState = AnimationStateDone; endAnimation(true); return; @@ -743,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->addToStyleAvailableWaitList(this); + m_compAnim->animationController()->addToStyleAvailableWaitList(this); // Trigger a render so we can start the animation if (m_object) - m_compAnim->animationControllerPriv()->addNodeChangeToDispatch(m_object->node()); + 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 @@ -776,7 +787,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) } else { bool started = startAnimation(0); - m_compAnim->addToStartTimeResponseWaitList(this, started); + m_compAnim->animationController()->addToStartTimeResponseWaitList(this, started); m_fallbackAnimating = !started; } break; @@ -792,9 +803,9 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) // Decide whether to go into looping or ending state goIntoEndingOrLoopingState(); - // Dispatch updateRendering so we can start the animation + // Dispatch updateStyleIfNeeded so we can start the animation if (m_object) - m_compAnim->animationControllerPriv()->addNodeChangeToDispatch(m_object->node()); + 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 @@ -834,7 +845,7 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) resumeOverriddenAnimations(); // Fire off another style change so we can set the final value - m_compAnim->animationControllerPriv()->addNodeChangeToDispatch(m_object->node()); + m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node()); } } else { // We are pausing while running. Cancel the animation and wait @@ -891,8 +902,8 @@ void AnimationBase::updateStateMachine(AnimStateInput input, double param) updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime()); m_fallbackAnimating = true; } else { - bool started = startAnimation(0); - m_compAnim->addToStartTimeResponseWaitList(this, started); + bool started = startAnimation(m_startTime); + m_compAnim->animationController()->addToStartTimeResponseWaitList(this, started); m_fallbackAnimating = !started; } break; @@ -958,7 +969,7 @@ void AnimationBase::updatePlayState(bool run) updateStateMachine(run ? AnimationStateInputPlayStateRunnning : AnimationStateInputPlayStatePaused, -1); } -double AnimationBase::willNeedService() +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. @@ -1062,7 +1073,7 @@ void AnimationBase::pauseAtTime(double t) double AnimationBase::beginAnimationUpdateTime() const { - return m_compAnim->animationControllerPriv()->beginAnimationUpdateTime(); + return m_compAnim->animationController()->beginAnimationUpdateTime(); } double AnimationBase::getElapsedTime() const diff --git a/WebCore/page/animation/AnimationBase.h b/WebCore/page/animation/AnimationBase.h index da4341b..8f55a8e 100644 --- a/WebCore/page/animation/AnimationBase.h +++ b/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); @@ -120,7 +120,7 @@ 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; } - virtual double willNeedService(); + virtual double timeToNextService(); double progress(double scale, double offset, const TimingFunction*) const; @@ -186,7 +186,7 @@ protected: virtual void onAnimationIteration(double /*elapsedTime*/) { } virtual void onAnimationEnd(double /*elapsedTime*/) { } virtual bool startAnimation(double /*beginTime*/) { return false; } - virtual void endAnimation(bool /*reset*/, double /*forcePauseTime*/ = -1) { } + virtual void endAnimation(bool /*reset*/) { } void goIntoEndingOrLoopingState(); @@ -199,7 +199,7 @@ protected: // Return true if we need to start software animation timers static bool blendProperties(const AnimationBase* anim, int prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress); - static void setChanged(Node*); + static void setNeedsStyleRecalc(Node*); void getTimeToNextEvent(double& time, bool& isLooping) const; diff --git a/WebCore/page/animation/AnimationController.cpp b/WebCore/page/animation/AnimationController.cpp index f9c9a47..58a1f5b 100644 --- a/WebCore/page/animation/AnimationController.cpp +++ b/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 @@ -35,7 +35,7 @@ #include "CompositeAnimation.h" #include "EventNames.h" #include "Frame.h" -#include "RenderObject.h" +#include "RenderView.h" #include <wtf/CurrentTime.h> #include <wtf/UnusedParam.h> @@ -46,7 +46,7 @@ static const double cBeginAnimationUpdateTimeNotSet = -1; 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) @@ -74,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; @@ -89,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; + CompositeAnimation* compAnim = it->second.get(); if (!compAnim->isSuspended() && compAnim->hasAnimations()) { - double t = compAnim->willNeedService(); + double t = compAnim->timeToNextService(); if (t != -1 && (t < needsService || needsService == -1)) needsService = t; if (needsService == 0) { if (callSetChanged) { Node* node = it->first->node(); ASSERT(!node || (node->document() && !node->document()->inPageCache())); - node->setChanged(AnimationStyleChange); + node->setNeedsStyleRecalc(AnimationStyleChange); calledSetChanged = true; } else @@ -108,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) { @@ -130,7 +130,7 @@ 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 eventsToDispatchEnd = m_eventsToDispatch.end(); @@ -146,18 +146,32 @@ void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationC // 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)->setChanged(AnimationStyleChange); + (*it)->setNeedsStyleRecalc(AnimationStyleChange); m_nodeChangesToDispatch.clear(); if (m_frame) - m_frame->document()->updateRendering(); + 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) @@ -169,7 +183,7 @@ void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, event.name = name; event.elapsedTime = elapsedTime; - startUpdateRenderingDispatcher(); + startUpdateStyleIfNeededDispatcher(); } void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node) @@ -179,7 +193,7 @@ void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node) return; m_nodeChangesToDispatch.append(node); - startUpdateRenderingDispatcher(); + startUpdateStyleIfNeededDispatcher(); } void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>*) @@ -189,7 +203,7 @@ void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPr 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); } @@ -204,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(); @@ -217,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(); @@ -238,8 +258,8 @@ bool AnimationControllerPrivate::pauseAnimationAtTime(RenderObject* renderer, co return false; if (compAnim->pauseAnimationAtTime(name, t)) { - renderer->node()->setChanged(AnimationStyleChange); - startUpdateRenderingDispatcher(); + renderer->node()->setNeedsStyleRecalc(AnimationStyleChange); + startUpdateStyleIfNeededDispatcher(); return true; } @@ -256,8 +276,8 @@ bool AnimationControllerPrivate::pauseTransitionAtTime(RenderObject* renderer, c return false; if (compAnim->pauseTransitionAtTime(cssPropertyID(property), t)) { - renderer->node()->setChanged(AnimationStyleChange); - startUpdateRenderingDispatcher(); + renderer->node()->setNeedsStyleRecalc(AnimationStyleChange); + startUpdateStyleIfNeededDispatcher(); return true; } @@ -365,7 +385,7 @@ void AnimationControllerPrivate::addToStartTimeResponseWaitList(AnimationBase* a // In the second case, we just pass in the beginAnimationUpdateTime(). // // This will synchronize all software and accelerated animations started in the same - // updateRendering cycle. + // updateStyleIfNeeded cycle. // ASSERT(!animation->next()); @@ -432,7 +452,7 @@ void AnimationController::cancelAnimations(RenderObject* renderer) if (m_data->clear(renderer)) { Node* node = renderer->node(); ASSERT(!node || (node->document() && !node->document()->inPageCache())); - node->setChanged(AnimationStyleChange); + node->setNeedsStyleRecalc(AnimationStyleChange); } } @@ -447,6 +467,10 @@ 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 diff --git a/WebCore/page/animation/AnimationControllerPrivate.h b/WebCore/page/animation/AnimationControllerPrivate.h index f9a3405..359b9b5 100644 --- a/WebCore/page/animation/AnimationControllerPrivate.h +++ b/WebCore/page/animation/AnimationControllerPrivate.h @@ -60,8 +60,8 @@ public: void animationTimerFired(Timer<AnimationControllerPrivate>*); void updateAnimationTimer(bool callSetChanged = false); - void updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*); - void startUpdateRenderingDispatcher(); + void updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*); + void startUpdateStyleIfNeededDispatcher(); void addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime); void addNodeChangeToDispatch(PassRefPtr<Node>); @@ -107,7 +107,7 @@ private: RenderObjectAnimationMap m_compositeAnimations; Timer<AnimationControllerPrivate> m_animationTimer; - Timer<AnimationControllerPrivate> m_updateRenderingDispatcher; + Timer<AnimationControllerPrivate> m_updateStyleIfNeededDispatcher; Frame* m_frame; class EventToDispatch { diff --git a/WebCore/page/animation/CompositeAnimation.cpp b/WebCore/page/animation/CompositeAnimation.cpp index d386f1b..d60455a 100644 --- a/WebCore/page/animation/CompositeAnimation.cpp +++ b/WebCore/page/animation/CompositeAnimation.cpp @@ -38,78 +38,14 @@ namespace WebCore { -class CompositeAnimationPrivate { -public: - CompositeAnimationPrivate(AnimationControllerPrivate* 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); - PassRefPtr<RenderStyle> getAnimatedStyle(); - - AnimationControllerPrivate* animationControllerPriv() const { return m_animationController; } - - void setAnimating(bool); - double willNeedService() const; - - PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property); - - void cleanupFinishedAnimations(RenderObject*); - - void suspendAnimations(); - void resumeAnimations(); - bool isSuspended() const { return m_isSuspended; } - - void overrideImplicitAnimations(int property); - void resumeOverriddenImplicitAnimations(int property); - - bool hasAnimations() const { return !m_transitions.isEmpty() || !m_keyframeAnimations.isEmpty(); } - - bool isAnimatingProperty(int property, bool isRunningNow) const; - - void addToStyleAvailableWaitList(AnimationBase*); - void removeFromStyleAvailableWaitList(AnimationBase*); - - void addToStartTimeResponseWaitList(AnimationBase*, bool willGetResponse); - void removeFromStartTimeResponseWaitList(AnimationBase*); - - bool pauseAnimationAtTime(const AtomicString& name, double t); - bool pauseTransitionAtTime(int property, double t); - unsigned numberOfActiveAnimations() const; - -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; - Vector<AtomicStringImpl*> m_keyframeAnimationOrderMap; - bool m_isSuspended; - AnimationControllerPrivate* 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() { if (!m_transitions.isEmpty()) { // Clear the renderers from all running animations, in case we are in the middle of @@ -129,7 +65,7 @@ void CompositeAnimationPrivate::clearRenderer() } } -void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) +void CompositeAnimation::updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) { RefPtr<RenderStyle> modifiedCurrentStyle; @@ -174,7 +110,11 @@ void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, Render bool equal = true; if (implAnim) { - // This implAnim might not be an already running transition. It might be + // 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 @@ -198,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, modifiedCurrentStyle ? modifiedCurrentStyle.get() : 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 @@ -210,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()) @@ -251,7 +195,7 @@ 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); } @@ -275,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; @@ -292,7 +236,7 @@ PassRefPtr<RenderStyle> CompositeAnimationPrivate::animate(RenderObject* rendere 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); + anim->animate(this, renderer, currentStyle, targetStyle, resultStyle); } } } @@ -302,15 +246,15 @@ PassRefPtr<RenderStyle> CompositeAnimationPrivate::animate(RenderObject* rendere for (Vector<AtomicStringImpl*>::const_iterator it = m_keyframeAnimationOrderMap.begin(); it != m_keyframeAnimationOrderMap.end(); ++it) { RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(*it); if (keyframeAnim) - keyframeAnim->animate(m_compositeAnimation, renderer, currentStyle, targetStyle, resultStyle); + keyframeAnim->animate(this, renderer, currentStyle, targetStyle, resultStyle); } - cleanupFinishedAnimations(renderer); + cleanupFinishedAnimations(); return resultStyle ? resultStyle.release() : targetStyle; } -PassRefPtr<RenderStyle> CompositeAnimationPrivate::getAnimatedStyle() +PassRefPtr<RenderStyle> CompositeAnimation::getAnimatedStyle() const { RefPtr<RenderStyle> resultStyle; CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); @@ -329,7 +273,7 @@ PassRefPtr<RenderStyle> CompositeAnimationPrivate::getAnimatedStyle() } // "animating" means that something is running that requires the timer to keep firing -void CompositeAnimationPrivate::setAnimating(bool animating) +void CompositeAnimation::setAnimating(bool animating) { if (!m_transitions.isEmpty()) { CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); @@ -347,7 +291,7 @@ void CompositeAnimationPrivate::setAnimating(bool 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. @@ -357,7 +301,7 @@ double CompositeAnimationPrivate::willNeedService() const 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; + double t = transition ? transition->timeToNextService() : -1; if (t < minT || minT == -1) minT = t; if (minT == 0) @@ -368,7 +312,7 @@ double CompositeAnimationPrivate::willNeedService() const 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; + double t = animation ? animation->timeToNextService() : -1; if (t < minT || minT == -1) minT = t; if (minT == 0) @@ -379,7 +323,7 @@ double CompositeAnimationPrivate::willNeedService() const return minT; } -PassRefPtr<KeyframeAnimation> CompositeAnimationPrivate::getAnimationForProperty(int property) +PassRefPtr<KeyframeAnimation> CompositeAnimation::getAnimationForProperty(int property) const { RefPtr<KeyframeAnimation> retval; @@ -397,7 +341,7 @@ PassRefPtr<KeyframeAnimation> CompositeAnimationPrivate::getAnimationForProperty return retval; } -void CompositeAnimationPrivate::cleanupFinishedAnimations(RenderObject*) +void CompositeAnimation::cleanupFinishedAnimations() { if (isSuspended()) return; @@ -441,7 +385,7 @@ void CompositeAnimationPrivate::cleanupFinishedAnimations(RenderObject*) } } -void CompositeAnimationPrivate::suspendAnimations() +void CompositeAnimation::suspendAnimations() { if (m_isSuspended) return; @@ -465,7 +409,7 @@ void CompositeAnimationPrivate::suspendAnimations() } } -void CompositeAnimationPrivate::resumeAnimations() +void CompositeAnimation::resumeAnimations() { if (!m_isSuspended) return; @@ -491,7 +435,7 @@ void CompositeAnimationPrivate::resumeAnimations() } } -void CompositeAnimationPrivate::overrideImplicitAnimations(int property) +void CompositeAnimation::overrideImplicitAnimations(int property) { CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); if (!m_transitions.isEmpty()) { @@ -503,7 +447,7 @@ void CompositeAnimationPrivate::overrideImplicitAnimations(int property) } } -void CompositeAnimationPrivate::resumeOverriddenImplicitAnimations(int property) +void CompositeAnimation::resumeOverriddenImplicitAnimations(int property) { if (!m_transitions.isEmpty()) { CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); @@ -515,7 +459,7 @@ void CompositeAnimationPrivate::resumeOverriddenImplicitAnimations(int property) } } -bool CompositeAnimationPrivate::isAnimatingProperty(int property, bool isRunningNow) const +bool CompositeAnimation::isAnimatingProperty(int property, bool isRunningNow) const { if (!m_keyframeAnimations.isEmpty()) { AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); @@ -537,27 +481,7 @@ bool CompositeAnimationPrivate::isAnimatingProperty(int property, bool isRunning return false; } -void CompositeAnimationPrivate::addToStyleAvailableWaitList(AnimationBase* animation) -{ - m_animationController->addToStyleAvailableWaitList(animation); -} - -void CompositeAnimationPrivate::removeFromStyleAvailableWaitList(AnimationBase* animation) -{ - m_animationController->removeFromStyleAvailableWaitList(animation); -} - -void CompositeAnimationPrivate::addToStartTimeResponseWaitList(AnimationBase* animation, bool willGetResponse) -{ - m_animationController->addToStartTimeResponseWaitList(animation, willGetResponse); -} - -void CompositeAnimationPrivate::removeFromStartTimeResponseWaitList(AnimationBase* animation) -{ - m_animationController->removeFromStartTimeResponseWaitList(animation); -} - -bool CompositeAnimationPrivate::pauseAnimationAtTime(const AtomicString& name, double t) +bool CompositeAnimation::pauseAnimationAtTime(const AtomicString& name, double t) { if (!name) return false; @@ -575,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; @@ -592,7 +516,7 @@ bool CompositeAnimationPrivate::pauseTransitionAtTime(int property, double t) return false; } -unsigned CompositeAnimationPrivate::numberOfActiveAnimations() const +unsigned CompositeAnimation::numberOfActiveAnimations() const { unsigned count = 0; @@ -617,119 +541,4 @@ unsigned CompositeAnimationPrivate::numberOfActiveAnimations() const return count; } -CompositeAnimation::CompositeAnimation(AnimationControllerPrivate* animationController) - : m_data(new CompositeAnimationPrivate(animationController, this)) -{ -} - -CompositeAnimation::~CompositeAnimation() -{ - delete m_data; -} - -AnimationControllerPrivate* CompositeAnimation::animationControllerPriv() const -{ - return m_data->animationControllerPriv(); -} - -void CompositeAnimation::clearRenderer() -{ - m_data->clearRenderer(); -} - -PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) -{ - return m_data->animate(renderer, currentStyle, targetStyle); -} - -PassRefPtr<RenderStyle> CompositeAnimation::getAnimatedStyle() -{ - return m_data->getAnimatedStyle(); -} - -double CompositeAnimation::willNeedService() const -{ - return m_data->willNeedService(); -} - -void CompositeAnimation::addToStyleAvailableWaitList(AnimationBase* animation) -{ - m_data->addToStyleAvailableWaitList(animation); -} - -void CompositeAnimation::removeFromStyleAvailableWaitList(AnimationBase* animation) -{ - m_data->removeFromStyleAvailableWaitList(animation); -} - -void CompositeAnimation::addToStartTimeResponseWaitList(AnimationBase* animation, bool willGetResponse) -{ - m_data->addToStartTimeResponseWaitList(animation, willGetResponse); -} - -void CompositeAnimation::removeFromStartTimeResponseWaitList(AnimationBase* animation) -{ - m_data->removeFromStartTimeResponseWaitList(animation); -} - -void CompositeAnimation::suspendAnimations() -{ - m_data->suspendAnimations(); -} - -void CompositeAnimation::resumeAnimations() -{ - m_data->resumeAnimations(); -} - -bool CompositeAnimation::isSuspended() const -{ - return m_data->isSuspended(); -} - -bool CompositeAnimation::hasAnimations() const -{ - return m_data->hasAnimations(); -} - -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::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/WebCore/page/animation/CompositeAnimation.h b/WebCore/page/animation/CompositeAnimation.h index b5857aa..739cfdc 100644 --- a/WebCore/page/animation/CompositeAnimation.h +++ b/WebCore/page/animation/CompositeAnimation.h @@ -31,16 +31,15 @@ #include "AtomicString.h" +#include "ImplicitAnimation.h" +#include "KeyframeAnimation.h" #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> namespace WebCore { class AnimationControllerPrivate; -class CompositeAnimationPrivate; -class AnimationBase; class AnimationController; -class KeyframeAnimation; class RenderObject; class RenderStyle; @@ -58,28 +57,24 @@ public: void clearRenderer(); PassRefPtr<RenderStyle> animate(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle); - PassRefPtr<RenderStyle> getAnimatedStyle(); + PassRefPtr<RenderStyle> getAnimatedStyle() const; - double willNeedService() const; + double timeToNextService() const; - AnimationControllerPrivate* animationControllerPriv() const; - - void addToStyleAvailableWaitList(AnimationBase*); - void removeFromStyleAvailableWaitList(AnimationBase*); - - void addToStartTimeResponseWaitList(AnimationBase*, bool willGetResponse); - void removeFromStartTimeResponseWaitList(AnimationBase*); + AnimationControllerPrivate* animationController() const { return m_animationController; } void suspendAnimations(); void resumeAnimations(); - bool isSuspended() const; + bool isSuspended() const { return m_isSuspended; } - bool hasAnimations() const; + bool hasAnimations() const { return !m_transitions.isEmpty() || !m_keyframeAnimations.isEmpty(); } void setAnimating(bool); bool isAnimatingProperty(int property, bool isRunningNow) const; - PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property); + PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property) const; + + void cleanupFinishedAnimations(); void overrideImplicitAnimations(int property); void resumeOverriddenImplicitAnimations(int property); @@ -89,9 +84,25 @@ public: unsigned numberOfActiveAnimations() const; private: - CompositeAnimation(AnimationControllerPrivate* 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/WebCore/page/animation/ImplicitAnimation.cpp b/WebCore/page/animation/ImplicitAnimation.cpp index 8ec0be0..e93fee4 100644 --- a/WebCore/page/animation/ImplicitAnimation.cpp +++ b/WebCore/page/animation/ImplicitAnimation.cpp @@ -52,9 +52,9 @@ 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) const @@ -167,11 +167,11 @@ bool ImplicitAnimation::sendTransitionEvent(const AtomicString& eventType, doubl return false; // Schedule event handling - m_compAnim->animationControllerPriv()->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 } @@ -216,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)); } @@ -255,9 +261,9 @@ void ImplicitAnimation::validateTransformFunctionList() m_transformFunctionListValid = true; } -double ImplicitAnimation::willNeedService() +double ImplicitAnimation::timeToNextService() { - double t = AnimationBase::willNeedService(); + double t = AnimationBase::timeToNextService(); #if USE(ACCELERATED_COMPOSITING) if (t != 0 || preActive()) return t; diff --git a/WebCore/page/animation/ImplicitAnimation.h b/WebCore/page/animation/ImplicitAnimation.h index 221c45e..33fe4e4 100644 --- a/WebCore/page/animation/ImplicitAnimation.h +++ b/WebCore/page/animation/ImplicitAnimation.h @@ -65,7 +65,7 @@ public: void blendPropertyValueInStyle(int, RenderStyle* currentStyle); - virtual double willNeedService(); + virtual double timeToNextService(); protected: bool shouldSendEventForListener(Document::ListenerType) const; diff --git a/WebCore/page/animation/KeyframeAnimation.cpp b/WebCore/page/animation/KeyframeAnimation.cpp index 88a5f6a..3f84de1 100644 --- a/WebCore/page/animation/KeyframeAnimation.cpp +++ b/WebCore/page/animation/KeyframeAnimation.cpp @@ -56,9 +56,9 @@ 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 @@ -216,7 +216,8 @@ void KeyframeAnimation::endAnimation(bool reset) UNUSED_PARAM(reset); #endif // Restore the original (unanimated) style - setChanged(m_object->node()); + if (!paused()) + setNeedsStyleRecalc(m_object->node()); } } @@ -266,11 +267,11 @@ bool KeyframeAnimation::sendAnimationEvent(const AtomicString& eventType, double return false; // Schedule event handling - m_compAnim->animationControllerPriv()->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 } @@ -352,9 +353,9 @@ void KeyframeAnimation::validateTransformFunctionList() m_transformFunctionListValid = true; } -double KeyframeAnimation::willNeedService() +double KeyframeAnimation::timeToNextService() { - double t = AnimationBase::willNeedService(); + double t = AnimationBase::timeToNextService(); #if USE(ACCELERATED_COMPOSITING) if (t != 0 || preActive()) return t; diff --git a/WebCore/page/animation/KeyframeAnimation.h b/WebCore/page/animation/KeyframeAnimation.h index 1090e5b..4905fc3 100644 --- a/WebCore/page/animation/KeyframeAnimation.h +++ b/WebCore/page/animation/KeyframeAnimation.h @@ -57,7 +57,7 @@ public: void setUnanimatedStyle(PassRefPtr<RenderStyle> style) { m_unanimatedStyle = style; } RenderStyle* unanimatedStyle() const { return m_unanimatedStyle.get(); } - virtual double willNeedService(); + virtual double timeToNextService(); protected: virtual void onAnimationStart(double elapsedTime); diff --git a/WebCore/page/chromium/AXObjectCacheChromium.cpp b/WebCore/page/chromium/AXObjectCacheChromium.cpp deleted file mode 100644 index bbaf21d..0000000 --- a/WebCore/page/chromium/AXObjectCacheChromium.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * Copyright (C) 2008 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "AXObjectCache.h" - -#include "AccessibilityObject.h" - -namespace WebCore { - -void AXObjectCache::detachWrapper(AccessibilityObject* obj) -{ - // In Chromium, AccessibilityObjects are wrapped lazily. - if (AccessibilityObjectWrapper* wrapper = obj->wrapper()) - wrapper->detach(); -} - -void AXObjectCache::attachWrapper(AccessibilityObject*) -{ - // In Chromium, AccessibilityObjects are wrapped lazily. -} - -void AXObjectCache::postNotification(RenderObject*, const String&) -{ -} - -void AXObjectCache::postNotificationToElement(RenderObject*, const String&) -{ -} - -void AXObjectCache::handleFocusedUIElementChanged() -{ -} - -} // namespace WebCore diff --git a/WebCore/page/chromium/AccessibilityObjectChromium.cpp b/WebCore/page/chromium/AccessibilityObjectChromium.cpp deleted file mode 100644 index 650fb3a..0000000 --- a/WebCore/page/chromium/AccessibilityObjectChromium.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * Copyright (C) 2008 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "AccessibilityObject.h" - -namespace WebCore { - -bool AccessibilityObject::accessibilityIgnoreAttachment() const -{ - return false; -} - -} // namespace WebCore diff --git a/WebCore/page/chromium/AccessibilityObjectWrapper.h b/WebCore/page/chromium/AccessibilityObjectWrapper.h deleted file mode 100644 index 6420b32..0000000 --- a/WebCore/page/chromium/AccessibilityObjectWrapper.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * Copyright (C) 2008 Google Inc. - * - * 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 AccessibilityObjectWrapper_h -#define AccessibilityObjectWrapper_h - -namespace WebCore { - - 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) - : m_object(obj) - { - // FIXME: Remove this once our immediate subclass no longer uses COM. - m_refCount = 0; - } - AccessibilityObjectWrapper() : m_object(0) { } - - AccessibilityObject* m_object; - }; - -} // namespace WebCore - -#endif diff --git a/WebCore/page/chromium/ChromeClientChromium.h b/WebCore/page/chromium/ChromeClientChromium.h index 5821dff..f6689d3 100644 --- a/WebCore/page/chromium/ChromeClientChromium.h +++ b/WebCore/page/chromium/ChromeClientChromium.h @@ -35,8 +35,8 @@ #include <wtf/Forward.h> namespace WebCore { - class FramelessScrollView; class IntRect; + class PopupContainer; // Contains Chromium-specific extensions to the ChromeClient. Only put // things here that don't make sense for other ports. @@ -44,7 +44,10 @@ namespace WebCore { public: // Notifies the client of a new popup widget. The client should place // and size the widget with the given bounds, relative to the screen. - virtual void popupOpened(FramelessScrollView* popupView, const IntRect& bounds, bool focusOnShow) = 0; + // If handleExternal is true, then drawing and input handling for the + // popup will be handled by the external embedder. + virtual void popupOpened(PopupContainer* popupContainer, const IntRect& bounds, + bool focusOnShow, bool handleExternal) = 0; }; } // namespace WebCore diff --git a/WebCore/page/chromium/FrameChromium.cpp b/WebCore/page/chromium/FrameChromium.cpp index d85fbcc..5253bbc 100644 --- a/WebCore/page/chromium/FrameChromium.cpp +++ b/WebCore/page/chromium/FrameChromium.cpp @@ -60,7 +60,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); diff --git a/WebCore/page/gtk/AXObjectCacheAtk.cpp b/WebCore/page/gtk/AXObjectCacheAtk.cpp deleted file mode 100644 index 3535cf1..0000000 --- a/WebCore/page/gtk/AXObjectCacheAtk.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008 Nuanti Ltd. - * - * 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 "AXObjectCache.h" - -#include "AccessibilityObject.h" -#include "AccessibilityObjectWrapperAtk.h" - -namespace WebCore { - -void AXObjectCache::detachWrapper(AccessibilityObject* obj) -{ - webkit_accessible_detach(WEBKIT_ACCESSIBLE(obj->wrapper())); -} - -void AXObjectCache::attachWrapper(AccessibilityObject* obj) -{ - AtkObject* atkObj = ATK_OBJECT(webkit_accessible_new(obj)); - obj->setWrapper(atkObj); - g_object_unref(atkObj); -} - -void AXObjectCache::postNotification(RenderObject*, const String&) -{ -} - -void AXObjectCache::postNotificationToElement(RenderObject*, const String&) -{ -} - -void AXObjectCache::handleFocusedUIElementChanged() -{ -} - -} // namespace WebCore diff --git a/WebCore/page/gtk/AccessibilityObjectAtk.cpp b/WebCore/page/gtk/AccessibilityObjectAtk.cpp deleted file mode 100644 index 1710027..0000000 --- a/WebCore/page/gtk/AccessibilityObjectAtk.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2008 Apple Ltd. - * - * 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 "AccessibilityObject.h" - -#if HAVE(ACCESSIBILITY) - -namespace WebCore { - -bool AccessibilityObject::accessibilityIgnoreAttachment() const -{ - return false; -} - -} // namespace WebCore - -#endif // HAVE(ACCESSIBILITY) diff --git a/WebCore/page/gtk/AccessibilityObjectWrapperAtk.cpp b/WebCore/page/gtk/AccessibilityObjectWrapperAtk.cpp deleted file mode 100644 index 84f3d34..0000000 --- a/WebCore/page/gtk/AccessibilityObjectWrapperAtk.cpp +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Copyright (C) 2008 Nuanti Ltd. - * - * 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 "AccessibilityObjectWrapperAtk.h" - -#if HAVE(ACCESSIBILITY) - -#include "AXObjectCache.h" -#include "AccessibilityListBox.h" -#include "AccessibilityRenderObject.h" -#include "AtomicString.h" -#include "CString.h" -#include "Document.h" -#include "Editor.h" -#include "Frame.h" -#include "FrameView.h" -#include "IntRect.h" -#include "NotImplemented.h" - -#include <atk/atk.h> - -using namespace WebCore; - -// Used to provide const char* returns. -static const char* returnString(const String& str) -{ - static CString returnedString; - returnedString = str.utf8(); - return returnedString.data(); -} - -static AccessibilityObject* core(WebKitAccessible* accessible) -{ - if (!accessible) - return 0; - - return accessible->m_object; -} - -static AccessibilityObject* core(AtkObject* object) -{ - if (!WEBKIT_IS_ACCESSIBLE(object)) - return 0; - - return core(WEBKIT_ACCESSIBLE(object)); -} - -static AccessibilityObject* core(AtkAction* action) -{ - return core(ATK_OBJECT(action)); -} - -static AccessibilityObject* core(AtkStreamableContent* streamable) -{ - return core(ATK_OBJECT(streamable)); -} - -static AccessibilityObject* core(AtkText* text) -{ - return core(ATK_OBJECT(text)); -} - -static AccessibilityObject* core(AtkEditableText* text) -{ - return core(ATK_OBJECT(text)); -} - -extern "C" { - -static gpointer parent_class = NULL; - -static void webkit_accessible_init(AtkObject* object, gpointer data) -{ - g_return_if_fail(WEBKIT_IS_ACCESSIBLE(object)); - g_return_if_fail(data); - - if (ATK_OBJECT_CLASS(parent_class)->initialize) - ATK_OBJECT_CLASS(parent_class)->initialize(object, data); - - WEBKIT_ACCESSIBLE(object)->m_object = reinterpret_cast<AccessibilityObject*>(data); -} - -static void webkit_accessible_finalize(GObject* object) -{ - // This is a good time to clear the return buffer. - returnString(String()); - - if (G_OBJECT_CLASS(parent_class)->finalize) - G_OBJECT_CLASS(parent_class)->finalize(object); -} - -static const gchar* webkit_accessible_get_name(AtkObject* object) -{ - // TODO: Deal with later changes. - if (!object->name) - atk_object_set_name(object, core(object)->stringValue().utf8().data()); - return object->name; -} - -static const gchar* webkit_accessible_get_description(AtkObject* object) -{ - // TODO: the Mozilla MSAA implementation prepends "Description: " - // Should we do this too? - - // TODO: Deal with later changes. - if (!object->description) - atk_object_set_description(object, core(object)->accessibilityDescription().utf8().data()); - return object->description; -} - -static AtkObject* webkit_accessible_get_parent(AtkObject* object) -{ - AccessibilityObject* coreParent = core(object)->parentObject(); - - if (!coreParent) - return NULL; - - return coreParent->wrapper(); -} - -static gint webkit_accessible_get_n_children(AtkObject* object) -{ - return core(object)->children().size(); -} - -static AtkObject* webkit_accessible_ref_child(AtkObject* object, gint index) -{ - AccessibilityObject* coreObject = core(object); - - g_return_val_if_fail(index >= 0, NULL); - g_return_val_if_fail(static_cast<size_t>(index) < coreObject->children().size(), NULL); - - AccessibilityObject* coreChild = coreObject->children().at(index).get(); - - if (!coreChild) - return NULL; - - AtkObject* child = coreChild->wrapper(); - // TODO: Should we call atk_object_set_parent() here? - //atk_object_set_parent(child, object); - g_object_ref(child); - - return child; -} - -static gint webkit_accessible_get_index_in_parent(AtkObject* object) -{ - // FIXME: This needs to be implemented. - notImplemented(); - return 0; -} - -static AtkRole atkRole(AccessibilityRole role) -{ - switch (role) { - case WebCore::ButtonRole: - return ATK_ROLE_PUSH_BUTTON; - case WebCore::RadioButtonRole: - return ATK_ROLE_RADIO_BUTTON; - case WebCore::CheckBoxRole: - return ATK_ROLE_CHECK_BOX; - case WebCore::SliderRole: - return ATK_ROLE_SLIDER; - case WebCore::TabGroupRole: - return ATK_ROLE_PAGE_TAB_LIST; - case WebCore::TextFieldRole: - case WebCore::TextAreaRole: - case WebCore::ListMarkerRole: - return ATK_ROLE_ENTRY; - case WebCore::StaticTextRole: - return ATK_ROLE_TEXT; //? - case WebCore::OutlineRole: - return ATK_ROLE_TREE; - case WebCore::ColumnRole: - return ATK_ROLE_UNKNOWN; //? - case WebCore::RowRole: - return ATK_ROLE_LIST_ITEM; - case WebCore::GroupRole: - return ATK_ROLE_UNKNOWN; //? - case WebCore::ListRole: - return ATK_ROLE_LIST; - case WebCore::TableRole: - return ATK_ROLE_TABLE; - case WebCore::LinkRole: - case WebCore::WebCoreLinkRole: - return ATK_ROLE_LINK; - case WebCore::ImageMapRole: - case WebCore::ImageRole: - return ATK_ROLE_IMAGE; - default: - return ATK_ROLE_UNKNOWN; - } -} - -static AtkRole webkit_accessible_get_role(AtkObject* object) -{ - return atkRole(core(object)->roleValue()); -} - -static void webkit_accessible_class_init(AtkObjectClass* klass) -{ - GObjectClass* gobject_class = G_OBJECT_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - klass->initialize = webkit_accessible_init; - - gobject_class->finalize = webkit_accessible_finalize; - - klass->get_name = webkit_accessible_get_name; - klass->get_description = webkit_accessible_get_description; - klass->get_parent = webkit_accessible_get_parent; - klass->get_n_children = webkit_accessible_get_n_children; - klass->ref_child = webkit_accessible_ref_child; - //klass->get_index_in_parent = webkit_accessible_get_index_in_parent; - klass->get_role = webkit_accessible_get_role; - //klass->get_attributes = webkit_accessible_get_attributes; - //klass->ref_state_set = webkit_accessible_ref_state_set; - //klass->ref_relation_set = webkit_accessible_ref_relation_set; -} - -static gboolean webkit_accessible_action_do_action(AtkAction* action, gint i) -{ - g_return_val_if_fail(i == 0, FALSE); - return core(action)->performDefaultAction(); -} - -static gint webkit_accessible_action_get_n_actions(AtkAction* action) -{ - return 1; -} - -static const gchar* webkit_accessible_action_get_description(AtkAction* action, gint i) -{ - g_return_val_if_fail(i == 0, NULL); - // TODO: Need a way to provide/localize action descriptions. - notImplemented(); - return ""; -} - -static const gchar* webkit_accessible_action_get_keybinding(AtkAction* action, gint i) -{ - g_return_val_if_fail(i == 0, NULL); - // FIXME: Construct a proper keybinding string. - return returnString(core(action)->accessKey().string()); -} - -static const gchar* webkit_accessible_action_get_name(AtkAction* action, gint i) -{ - g_return_val_if_fail(i == 0, NULL); - return returnString(core(action)->actionVerb()); -} - -static void atk_action_interface_init(AtkActionIface* iface) -{ - g_return_if_fail(iface); - - iface->do_action = webkit_accessible_action_do_action; - iface->get_n_actions = webkit_accessible_action_get_n_actions; - iface->get_description = webkit_accessible_action_get_description; - iface->get_keybinding = webkit_accessible_action_get_keybinding; - iface->get_name = webkit_accessible_action_get_name; -} - -// Text - -static gchar* webkit_accessible_text_get_text(AtkText* text, gint start_offset, gint end_offset) -{ - String ret = core(text)->doAXStringForRange(PlainTextRange(start_offset, end_offset - start_offset)); - // TODO: Intentionally copied? - return g_strdup(ret.utf8().data()); -} - -static gchar* webkit_accessible_text_get_text_after_offset(AtkText* text, gint offset, AtkTextBoundary boundary_type, gint* start_offset, gint* end_offset) -{ - notImplemented(); - return NULL; -} - -static gchar* webkit_accessible_text_get_text_at_offset(AtkText* text, gint offset, AtkTextBoundary boundary_type, gint* start_offset, gint* end_offset) -{ - notImplemented(); - return NULL; -} - -static gunichar webkit_accessible_text_get_character_at_offset(AtkText* text, gint offset) -{ - notImplemented(); - return 0; -} - -static gchar* webkit_accessible_text_get_text_before_offset(AtkText* text, gint offset, AtkTextBoundary boundary_type, gint* start_offset, gint* end_offset) -{ - notImplemented(); - return NULL; -} - -static gint webkit_accessible_text_get_caret_offset(AtkText* text) -{ - // TODO: Verify this, especially for RTL text. - return core(text)->selectionStart(); -} - -static AtkAttributeSet* webkit_accessible_text_get_run_attributes(AtkText* text, gint offset, gint* start_offset, gint* end_offset) -{ - notImplemented(); - return NULL; -} - -static AtkAttributeSet* webkit_accessible_text_get_default_attributes(AtkText* text) -{ - notImplemented(); - return NULL; -} - -static void webkit_accessible_text_get_character_extents(AtkText* text, gint offset, gint* x, gint* y, gint* width, gint* height, AtkCoordType coords) -{ - IntRect extents = core(text)->doAXBoundsForRange(PlainTextRange(offset, 1)); - // FIXME: Use the AtkCoordType - // Requires WebCore::ScrollView::contentsToScreen() to be implemented - -#if 0 - switch(coords) { - case ATK_XY_SCREEN: - extents = core(text)->document()->view()->contentsToScreen(extents); - break; - case ATK_XY_WINDOW: - // No-op - break; - } -#endif - - *x = extents.x(); - *y = extents.y(); - *width = extents.width(); - *height = extents.height(); -} - -static gint webkit_accessible_text_get_character_count(AtkText* text) -{ - return core(text)->textLength(); -} - -static gint webkit_accessible_text_get_offset_at_point(AtkText* text, gint x, gint y, AtkCoordType coords) -{ - // FIXME: Use the AtkCoordType - // TODO: Is it correct to ignore range.length? - IntPoint pos(x, y); - PlainTextRange range = core(text)->doAXRangeForPosition(pos); - return range.start; -} - -static gint webkit_accessible_text_get_n_selections(AtkText* text) -{ - notImplemented(); - return 0; -} - -static gchar* webkit_accessible_text_get_selection(AtkText* text, gint selection_num, gint* start_offset, gint* end_offset) -{ - notImplemented(); - return NULL; -} - -static gboolean webkit_accessible_text_add_selection(AtkText* text, gint start_offset, gint end_offset) -{ - notImplemented(); - return FALSE; -} - -static gboolean webkit_accessible_text_remove_selection(AtkText* text, gint selection_num) -{ - notImplemented(); - return FALSE; -} - -static gboolean webkit_accessible_text_set_selection(AtkText* text, gint selection_num, gint start_offset, gint end_offset) -{ - notImplemented(); - return FALSE; -} - -static gboolean webkit_accessible_text_set_caret_offset(AtkText* text, gint offset) -{ - // TODO: Verify - //core(text)->setSelectedTextRange(PlainTextRange(offset, 0)); - AccessibilityObject* coreObject = core(text); - coreObject->setSelectedVisiblePositionRange(coreObject->visiblePositionRangeForRange(PlainTextRange(offset, 0))); - return TRUE; -} - -#if 0 -// Signal handlers -static void webkit_accessible_text_text_changed(AtkText* text, gint position, gint length) -{ -} - -static void webkit_accessible_text_text_caret_moved(AtkText* text, gint location) -{ -} - -static void webkit_accessible_text_text_selection_changed(AtkText* text) -{ -} - -static void webkit_accessible_text_text_attributes_changed(AtkText* text) -{ -} - -static void webkit_accessible_text_get_range_extents(AtkText* text, gint start_offset, gint end_offset, AtkCoordType coord_type, AtkTextRectangle* rect) -{ -} - -static AtkTextRange** webkit_accessible_text_get_bounded_ranges(AtkText* text, AtkTextRectangle* rect, AtkCoordType coord_type, AtkTextClipType x_clip_type, AtkTextClipType y_clip_type) -{ -} -#endif - -static void atk_text_interface_init(AtkTextIface* iface) -{ - g_return_if_fail(iface); - - iface->get_text = webkit_accessible_text_get_text; - iface->get_text_after_offset = webkit_accessible_text_get_text_after_offset; - iface->get_text_at_offset = webkit_accessible_text_get_text_at_offset; - iface->get_character_at_offset = webkit_accessible_text_get_character_at_offset; - iface->get_text_before_offset = webkit_accessible_text_get_text_before_offset; - iface->get_caret_offset = webkit_accessible_text_get_caret_offset; - iface->get_run_attributes = webkit_accessible_text_get_run_attributes; - iface->get_default_attributes = webkit_accessible_text_get_default_attributes; - iface->get_character_extents = webkit_accessible_text_get_character_extents; - //iface->get_range_extents = ; - iface->get_character_count = webkit_accessible_text_get_character_count; - iface->get_offset_at_point = webkit_accessible_text_get_offset_at_point; - iface->get_n_selections = webkit_accessible_text_get_n_selections; - iface->get_selection = webkit_accessible_text_get_selection; - - // set methods - iface->add_selection = webkit_accessible_text_add_selection; - iface->remove_selection = webkit_accessible_text_remove_selection; - iface->set_selection = webkit_accessible_text_set_selection; - iface->set_caret_offset = webkit_accessible_text_set_caret_offset; -} - -// EditableText - -static gboolean webkit_accessible_editable_text_set_run_attributes(AtkEditableText* text, AtkAttributeSet* attrib_set, gint start_offset, gint end_offset) -{ - notImplemented(); - return FALSE; -} - -static void webkit_accessible_editable_text_set_text_contents(AtkEditableText* text, const gchar* string) -{ - // FIXME: string nullcheck? - core(text)->setValue(String::fromUTF8(string)); -} - -static void webkit_accessible_editable_text_insert_text(AtkEditableText* text, const gchar* string, gint length, gint* position) -{ - // FIXME: string nullcheck? - - AccessibilityObject* coreObject = core(text); - // FIXME: Not implemented in WebCore - //coreObject->setSelectedTextRange(PlainTextRange(*position, 0)); - //coreObject->setSelectedText(String::fromUTF8(string)); - - if (!coreObject->document() || !coreObject->document()->frame()) - return; - coreObject->setSelectedVisiblePositionRange(coreObject->visiblePositionRangeForRange(PlainTextRange(*position, 0))); - coreObject->setFocused(true); - // FIXME: We should set position to the actual inserted text length, which may be less than that requested. - if (coreObject->document()->frame()->editor()->insertTextWithoutSendingTextEvent(String::fromUTF8(string), false, 0)) - *position += length; -} - -static void webkit_accessible_editable_text_copy_text(AtkEditableText* text, gint start_pos, gint end_pos) -{ - notImplemented(); -} - -static void webkit_accessible_editable_text_cut_text(AtkEditableText* text, gint start_pos, gint end_pos) -{ - notImplemented(); -} - -static void webkit_accessible_editable_text_delete_text(AtkEditableText* text, gint start_pos, gint end_pos) -{ - AccessibilityObject* coreObject = core(text); - // FIXME: Not implemented in WebCore - //coreObject->setSelectedTextRange(PlainTextRange(start_pos, end_pos - start_pos)); - //coreObject->setSelectedText(String()); - - if (!coreObject->document() || !coreObject->document()->frame()) - return; - coreObject->setSelectedVisiblePositionRange(coreObject->visiblePositionRangeForRange(PlainTextRange(start_pos, end_pos - start_pos))); - coreObject->setFocused(true); - coreObject->document()->frame()->editor()->performDelete(); -} - -static void webkit_accessible_editable_text_paste_text(AtkEditableText* text, gint position) -{ - notImplemented(); -} - -static void atk_editable_text_interface_init(AtkEditableTextIface* iface) -{ - g_return_if_fail(iface); - - iface->set_run_attributes = webkit_accessible_editable_text_set_run_attributes; - iface->set_text_contents = webkit_accessible_editable_text_set_text_contents; - iface->insert_text = webkit_accessible_editable_text_insert_text; - iface->copy_text = webkit_accessible_editable_text_copy_text; - iface->cut_text = webkit_accessible_editable_text_cut_text; - iface->delete_text = webkit_accessible_editable_text_delete_text; - iface->paste_text = webkit_accessible_editable_text_paste_text; -} - -// StreamableContent - -static gint webkit_accessible_streamable_content_get_n_mime_types(AtkStreamableContent* streamable) -{ - notImplemented(); - return 0; -} - -static G_CONST_RETURN gchar* webkit_accessible_streamable_content_get_mime_type(AtkStreamableContent* streamable, gint i) -{ - notImplemented(); - return ""; -} - -static GIOChannel* webkit_accessible_streamable_content_get_stream(AtkStreamableContent* streamable, const gchar* mime_type) -{ - notImplemented(); - return NULL; -} - -static G_CONST_RETURN gchar* webkit_accessible_streamable_content_get_uri(AtkStreamableContent* streamable, const gchar* mime_type) -{ - notImplemented(); - return NULL; -} - -static void atk_streamable_content_interface_init(AtkStreamableContentIface* iface) -{ - g_return_if_fail(iface); - - iface->get_n_mime_types = webkit_accessible_streamable_content_get_n_mime_types; - iface->get_mime_type = webkit_accessible_streamable_content_get_mime_type; - iface->get_stream = webkit_accessible_streamable_content_get_stream; - iface->get_uri = webkit_accessible_streamable_content_get_uri; -} - -GType webkit_accessible_get_type() -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo tinfo = { - sizeof(WebKitAccessibleClass), - (GBaseInitFunc)NULL, - (GBaseFinalizeFunc)NULL, - (GClassInitFunc)webkit_accessible_class_init, - (GClassFinalizeFunc)NULL, - NULL, /* class data */ - sizeof(WebKitAccessible), /* instance size */ - 0, /* nb preallocs */ - (GInstanceInitFunc)NULL, - NULL /* value table */ - }; - - type = g_type_register_static(ATK_TYPE_OBJECT, "WebKitAccessible", &tinfo, static_cast<GTypeFlags>(0)); - - // TODO: Only implement interfaces when necessary, not for all objects. - static const GInterfaceInfo atk_action_info = - { - (GInterfaceInitFunc) atk_action_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - g_type_add_interface_static(type, ATK_TYPE_ACTION, &atk_action_info); - - static const GInterfaceInfo atk_text_info = - { - (GInterfaceInitFunc) atk_text_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - g_type_add_interface_static(type, ATK_TYPE_TEXT, &atk_text_info); - - static const GInterfaceInfo atk_editable_text_info = - { - (GInterfaceInitFunc) atk_editable_text_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - g_type_add_interface_static(type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info); - - static const GInterfaceInfo atk_streamable_content_info = - { - (GInterfaceInitFunc) atk_streamable_content_interface_init, - (GInterfaceFinalizeFunc) NULL, - NULL - }; - g_type_add_interface_static(type, ATK_TYPE_STREAMABLE_CONTENT, &atk_streamable_content_info); - } - return type; -} - -WebKitAccessible* webkit_accessible_new(AccessibilityObject* coreObject) -{ - GType type = WEBKIT_TYPE_ACCESSIBLE; - AtkObject* object = static_cast<AtkObject*>(g_object_new(type, NULL)); - atk_object_initialize(object, coreObject); - return WEBKIT_ACCESSIBLE(object); -} - -AccessibilityObject* webkit_accessible_get_accessibility_object(WebKitAccessible* accessible) -{ - return accessible->m_object; -} - -// FIXME: Remove this static initialization. -static AXObjectCache* fallbackCache = new AXObjectCache(); - -void webkit_accessible_detach(WebKitAccessible* accessible) -{ - ASSERT(accessible->m_object); - - // We replace the WebCore AccessibilityObject with a fallback object that - // provides default implementations to avoid repetitive null-checking after - // detachment. - - // FIXME: Using fallbackCache->get(ListBoxOptionRole) is a hack. - accessible->m_object = fallbackCache->getOrCreate(ListBoxOptionRole); -} - -} - -namespace WebCore { - -// AccessibilityObject implementations - -AccessibilityObjectWrapper* AccessibilityObject::wrapper() const -{ - return m_wrapper; -} - -void AccessibilityObject::setWrapper(AccessibilityObjectWrapper* wrapper) -{ - if (m_wrapper) - g_object_unref(m_wrapper); - - m_wrapper = wrapper; - - if (m_wrapper) - g_object_ref(m_wrapper); -} - -} // namespace WebCore - -#endif // HAVE(ACCESSIBILITY) diff --git a/WebCore/page/gtk/AccessibilityObjectWrapperAtk.h b/WebCore/page/gtk/AccessibilityObjectWrapperAtk.h deleted file mode 100644 index ecfb99e..0000000 --- a/WebCore/page/gtk/AccessibilityObjectWrapperAtk.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008 Nuanti Ltd. - * - * 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 AccessibilityObjectWrapperAtk_h -#define AccessibilityObjectWrapperAtk_h - -#include <atk/atk.h> - -namespace WebCore { - class AccessibilityObject; -} - -G_BEGIN_DECLS - -#define WEBKIT_TYPE_ACCESSIBLE (webkit_accessible_get_type ()) -#define WEBKIT_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_ACCESSIBLE, WebKitAccessible)) -#define WEBKIT_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_ACCESSIBLE, WebKitAccessibleClass)) -#define WEBKIT_IS_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_ACCESSIBLE)) -#define WEBKIT_IS_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_ACCESSIBLE)) -#define WEBKIT_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_ACCESSIBLE, WebKitAccessibleClass)) - -typedef struct _WebKitAccessible WebKitAccessible; -typedef struct _WebKitAccessibleClass WebKitAccessibleClass; - -struct _WebKitAccessible -{ - AtkObject parent; - WebCore::AccessibilityObject* m_object; -}; - -struct _WebKitAccessibleClass -{ - AtkObjectClass parent_class; -}; - -GType webkit_accessible_get_type (void) G_GNUC_CONST; - -WebKitAccessible* webkit_accessible_new (WebCore::AccessibilityObject* core_object); - -WebCore::AccessibilityObject* webkit_accessible_get_accessibility_object (WebKitAccessible* accessible); - -void webkit_accessible_detach (WebKitAccessible* accessible); - -G_END_DECLS - -#endif // AccessibilityObjectWrapperAtk_h diff --git a/WebCore/page/mac/AXObjectCacheMac.mm b/WebCore/page/mac/AXObjectCacheMac.mm deleted file mode 100644 index 936d9de..0000000 --- a/WebCore/page/mac/AXObjectCacheMac.mm +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2003, 2004, 2005, 2006, 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. - */ - -#import "config.h" -#import "AXObjectCache.h" - -#if HAVE(ACCESSIBILITY) - -#import "AccessibilityObject.h" -#import "AccessibilityObjectWrapper.h" -#import "RenderObject.h" -#import "WebCoreViewFactory.h" - -#import <wtf/PassRefPtr.h> - -// The simple Cocoa calls in this file don't throw exceptions. - -namespace WebCore { - -void AXObjectCache::detachWrapper(AccessibilityObject* obj) -{ - [obj->wrapper() detach]; - [obj->wrapper() release]; - obj->setWrapper(0); -} - -void AXObjectCache::attachWrapper(AccessibilityObject* obj) -{ - obj->setWrapper([[AccessibilityObjectWrapper alloc] initWithAccessibilityObject:obj]); -} - -void AXObjectCache::postNotification(RenderObject* renderer, const String& message) -{ - if (!renderer) - return; - - // notifications for text input objects are sent to that object - // all others are sent to the top WebArea - RefPtr<AccessibilityObject> obj = getOrCreate(renderer)->observableObject(); - if (!obj) - obj = getOrCreate(renderer->document()->renderer()); - - if (!obj) - return; - - NSAccessibilityPostNotification(obj->wrapper(), message); -} - -void AXObjectCache::postNotificationToElement(RenderObject* renderer, const String& message) -{ - // send the notification to the specified element itself, not one of its ancestors - if (!renderer) - return; - - RefPtr<AccessibilityObject> obj = getOrCreate(renderer); - if (!obj) - return; - - NSAccessibilityPostNotification(obj->wrapper(), message); -} - -void AXObjectCache::handleFocusedUIElementChanged() -{ - [[WebCoreViewFactory sharedFactory] accessibilityHandleFocusChanged]; -} - -} - -#endif // HAVE(ACCESSIBILITY) diff --git a/WebCore/page/mac/AccessibilityObjectMac.mm b/WebCore/page/mac/AccessibilityObjectMac.mm deleted file mode 100644 index 8f47af0..0000000 --- a/WebCore/page/mac/AccessibilityObjectMac.mm +++ /dev/null @@ -1,42 +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. - * - * 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. - */ - -#import "config.h" -#import "AccessibilityObject.h" - -#if HAVE(ACCESSIBILITY) - -#import "AccessibilityObjectWrapper.h" - -namespace WebCore { - -bool AccessibilityObject::accessibilityIgnoreAttachment() const -{ - return [[wrapper() attachmentView] accessibilityIsIgnored]; -} - -} // WebCore - -#endif // HAVE(ACCESSIBILITY) diff --git a/WebCore/page/mac/AccessibilityObjectWrapper.h b/WebCore/page/mac/AccessibilityObjectWrapper.h deleted file mode 100644 index 3b584a9..0000000 --- a/WebCore/page/mac/AccessibilityObjectWrapper.h +++ /dev/null @@ -1,60 +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 AccessibilityObjectWrapper_h -#define AccessibilityObjectWrapper_h - -#import <wtf/RefPtr.h> - -#ifdef __OBJC__ -@class WebCoreTextMarker; -@class WebCoreTextMarkerRange; -#else -class WebCoreTextMarker; -class WebCoreTextMarkerRange; -#endif - -namespace WebCore { - class AccessibilityObject; - class VisiblePosition; -} - -@interface AccessibilityObjectWrapper : NSObject -{ - WebCore::AccessibilityObject* m_object; -} - -- (id)initWithAccessibilityObject:(WebCore::AccessibilityObject*)axObject; -- (void)detach; -- (WebCore::AccessibilityObject*)accessibilityObject; - -- (NSView*)attachmentView; - -@end - -#endif // AccessibilityObjectWrapper_h diff --git a/WebCore/page/mac/AccessibilityObjectWrapper.mm b/WebCore/page/mac/AccessibilityObjectWrapper.mm deleted file mode 100644 index 1e596eb..0000000 --- a/WebCore/page/mac/AccessibilityObjectWrapper.mm +++ /dev/null @@ -1,2141 +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. - */ - -#import "config.h" -#import "AccessibilityObjectWrapper.h" - -#if HAVE(ACCESSIBILITY) - -#import "AXObjectCache.h" -#import "AccessibilityListBox.h" -#import "AccessibilityList.h" -#import "AccessibilityRenderObject.h" -#import "AccessibilityTable.h" -#import "AccessibilityTableCell.h" -#import "AccessibilityTableRow.h" -#import "AccessibilityTableColumn.h" -#import "ColorMac.h" -#import "Frame.h" -#import "HTMLAnchorElement.h" -#import "HTMLAreaElement.h" -#import "HTMLImageElement.h" -#import "HTMLInputElement.h" -#import "HTMLTextAreaElement.h" -#import "LocalizedStrings.h" -#import "RenderTextControl.h" -#import "RenderView.h" -#import "RenderWidget.h" -#import "SelectionController.h" -#import "SimpleFontData.h" -#import "TextIterator.h" -#import "WebCoreFrameView.h" -#import "WebCoreObjCExtras.h" -#import "WebCoreViewFactory.h" -#import "htmlediting.h" -#import "visible_units.h" -#import <runtime/InitializeThreading.h> - -using namespace WebCore; -using namespace HTMLNames; -using namespace std; - -// Cell Tables -#ifndef NSAccessibilitySelectedCellsAttribute -#define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells" -#endif - -#ifndef NSAccessibilityVisibleCellsAttribute -#define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells" -#endif - -#ifndef NSAccessibilityRowHeaderUIElementsAttribute -#define NSAccessibilityRowHeaderUIElementsAttribute @"AXRowHeaderUIElements" -#endif - -#ifndef NSAccessibilityRowIndexRangeAttribute -#define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange" -#endif - -#ifndef NSAccessibilityColumnIndexRangeAttribute -#define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange" -#endif - -#ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute -#define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow" -#endif - -#ifndef NSAccessibilityCellRole -#define NSAccessibilityCellRole @"AXCell" -#endif - -// Lists -#ifndef NSAccessibilityContentListSubrole -#define NSAccessibilityContentListSubrole @"AXContentList" -#endif - -#ifndef NSAccessibilityDefinitionListSubrole -#define NSAccessibilityDefinitionListSubrole @"AXDefinitionList" -#endif - -// Miscellaneous -#ifndef NSAccessibilityBlockQuoteLevelAttribute -#define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel" -#endif - -#ifndef NSAccessibilityAccessKeyAttribute -#define NSAccessibilityAccessKeyAttribute @"AXAccessKey" -#endif - -#ifdef BUILDING_ON_TIGER -typedef unsigned NSUInteger; -#endif - -@interface NSObject (WebKitAccessibilityArrayCategory) - -- (NSUInteger)accessibilityIndexOfChild:(id)child; -- (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute; -- (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount; - -@end - -@implementation AccessibilityObjectWrapper - -+ (void)initialize -{ - JSC::initializeThreading(); -#ifndef BUILDING_ON_TIGER - WebCoreObjCFinalizeOnMainThread(self); -#endif -} - -- (id)initWithAccessibilityObject:(AccessibilityObject*)axObject -{ - [super init]; - - m_object = axObject; - return self; -} - -- (void)unregisterUniqueIdForUIElement -{ - [[WebCoreViewFactory sharedFactory] unregisterUniqueIdForUIElement:self]; -} - -- (void)detach -{ - // Send unregisterUniqueIdForUIElement unconditionally because if it is - // ever accidently not done (via other bugs in our AX implementation) you - // end up with a crash like <rdar://problem/4273149>. It is safe and not - // expensive to send even if the object is not registered. - [self unregisterUniqueIdForUIElement]; - m_object = 0; -} - -- (AccessibilityObject*)accessibilityObject -{ - return m_object; -} - -- (NSView*)attachmentView -{ - ASSERT(m_object->isAttachment()); - Widget* widget = m_object->widgetForAttachmentView(); - if (!widget) - return nil; - return widget->platformWidget(); -} - -static WebCoreTextMarker* textMarkerForVisiblePosition(const VisiblePosition& visiblePos) -{ - if (visiblePos.isNull()) - return nil; - - Position deepPos = visiblePos.deepEquivalent(); - Node* domNode = deepPos.node(); - ASSERT(domNode); - if (!domNode) - return nil; - - if (domNode->isHTMLElement()) { - InputElement* inputElement = toInputElement(static_cast<Element*>(domNode)); - if (inputElement && inputElement->isPasswordField()) - return nil; - } - - // locate the renderer, which must exist for a visible dom node - RenderObject* renderer = domNode->renderer(); - ASSERT(renderer); - - // find or create an accessibility object for this renderer - AXObjectCache* cache = renderer->document()->axObjectCache(); - RefPtr<AccessibilityObject> obj = cache->getOrCreate(renderer); - - // create a text marker, adding an ID for the AccessibilityObject if needed - TextMarkerData textMarkerData; - - // The compiler can add padding to this struct. - // This memory must be bzero'd so instances of TextMarkerData can be tested for byte-equivalence. - bzero(&textMarkerData, sizeof(TextMarkerData)); - textMarkerData.axID = obj.get()->axObjectID(); - textMarkerData.node = domNode; - textMarkerData.offset = deepPos.m_offset; - textMarkerData.affinity = visiblePos.affinity(); - return [[WebCoreViewFactory sharedFactory] textMarkerWithBytes:&textMarkerData length:sizeof(textMarkerData)]; -} - -static VisiblePosition visiblePositionForTextMarker(WebCoreTextMarker* textMarker) -{ - TextMarkerData textMarkerData; - - if (![[WebCoreViewFactory sharedFactory] getBytes:&textMarkerData fromTextMarker:textMarker length:sizeof(textMarkerData)]) - return VisiblePosition(); - - VisiblePosition visiblePos = VisiblePosition(textMarkerData.node, textMarkerData.offset, textMarkerData.affinity); - Position deepPos = visiblePos.deepEquivalent(); - if (deepPos.isNull()) - return VisiblePosition(); - - RenderObject* renderer = deepPos.node()->renderer(); - if (!renderer) - return VisiblePosition(); - - AXObjectCache* cache = renderer->document()->axObjectCache(); - if (!cache->isIDinUse(textMarkerData.axID)) - return VisiblePosition(); - - if (deepPos.node() != textMarkerData.node || deepPos.m_offset != textMarkerData.offset) - return VisiblePosition(); - - return visiblePos; -} - -static VisiblePosition visiblePositionForStartOfTextMarkerRange(WebCoreTextMarkerRange* textMarkerRange) -{ - return visiblePositionForTextMarker([[WebCoreViewFactory sharedFactory] startOfTextMarkerRange:textMarkerRange]); -} - -static VisiblePosition visiblePositionForEndOfTextMarkerRange(WebCoreTextMarkerRange* textMarkerRange) -{ - return visiblePositionForTextMarker([[WebCoreViewFactory sharedFactory] endOfTextMarkerRange:textMarkerRange]); -} - -static WebCoreTextMarkerRange* textMarkerRangeFromMarkers(WebCoreTextMarker* textMarker1, WebCoreTextMarker* textMarker2) -{ - if (!textMarker1 || !textMarker2) - return nil; - - return [[WebCoreViewFactory sharedFactory] textMarkerRangeWithStart:textMarker1 end:textMarker2]; -} - -static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range) -{ - NSDictionary* dict; - - if (font) { - dict = [NSDictionary dictionaryWithObjectsAndKeys: - [font fontName] , NSAccessibilityFontNameKey, - [font familyName] , NSAccessibilityFontFamilyKey, - [font displayName] , NSAccessibilityVisibleNameKey, - [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey, - nil]; - - [attrString addAttribute:attribute value:dict range:range]; - } else - [attrString removeAttribute:attribute range:range]; - -} - -static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor) -{ - // get color information assuming NSDeviceRGBColorSpace - NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - if (rgbColor == nil) - rgbColor = [NSColor blackColor]; - CGFloat components[4]; - [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]]; - - // create a new CGColorRef to return - CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB(); - CGColorRef cgColor = CGColorCreate(cgColorSpace, components); - CGColorSpaceRelease(cgColorSpace); - - // check for match with existing color - if (existingColor && CGColorEqualToColor(cgColor, existingColor)) { - CGColorRelease(cgColor); - cgColor = 0; - } - - return cgColor; -} - -static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range) -{ - if (color) { - CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil]; - CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor); - if (cgColor) { - [attrString addAttribute:attribute value:(id)cgColor range:range]; - CGColorRelease(cgColor); - } - } else - [attrString removeAttribute:attribute range:range]; -} - -static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range) -{ - if (number) - [attrString addAttribute:attribute value:number range:range]; - else - [attrString removeAttribute:attribute range:range]; -} - -static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range) -{ - RenderStyle* style = renderer->style(); - - // set basic font info - AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style->font().primaryFont()->getNSFont(), range); - - // set basic colors - AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style->color()), range); - AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style->backgroundColor()), range); - - // set super/sub scripting - EVerticalAlign alignment = style->verticalAlign(); - if (alignment == SUB) - AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range); - else if (alignment == SUPER) - AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range); - else - [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range]; - - // set shadow - if (style->textShadow()) - AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range); - else - [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range]; - - // set underline and strikethrough - int decor = style->textDecorationsInEffect(); - if ((decor & UNDERLINE) == 0) { - [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range]; - [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range]; - } - - if ((decor & LINE_THROUGH) == 0) { - [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range]; - [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range]; - } - - if ((decor & (UNDERLINE | LINE_THROUGH)) != 0) { - // find colors using quirk mode approach (strict mode would use current - // color for all but the root line box, which would use getTextDecorationColors) - Color underline, overline, linethrough; - renderer->getTextDecorationColors(decor, underline, overline, linethrough); - - if ((decor & UNDERLINE) != 0) { - AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range); - AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underline), range); - } - - if ((decor & LINE_THROUGH) != 0) { - AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range); - AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethrough), range); - } - } -} - -static int blockquoteLevel(RenderObject* renderer) -{ - if (!renderer) - return 0; - - int result = 0; - for (Node* node = renderer->node(); node; node = node->parent()) { - if (node->hasTagName(blockquoteTag)) - result += 1; - } - - return result; -} - -static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range) -{ - int quoteLevel = blockquoteLevel(renderer); - - if (quoteLevel) - [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range]; - else - [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range]; -} - -static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, int offset, NSRange range) -{ - Vector<DocumentMarker> markers = node->renderer()->document()->markersForNode(node); - Vector<DocumentMarker>::iterator markerIt = markers.begin(); - - unsigned endOffset = (unsigned)offset + range.length; - for ( ; markerIt != markers.end(); markerIt++) { - DocumentMarker marker = *markerIt; - - if (marker.type != DocumentMarker::Spelling) - continue; - - if (marker.endOffset <= (unsigned)offset) - continue; - - if (marker.startOffset > endOffset) - break; - - // add misspelling attribute for the intersection of the marker and the range - int rStart = range.location + (marker.startOffset - offset); - int rLength = MIN(marker.endOffset, endOffset) - marker.startOffset; - NSRange spellRange = NSMakeRange(rStart, rLength); - AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange); - - if (marker.endOffset > endOffset + 1) - break; - } -} - -static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range) -{ - int parentHeadingLevel = AccessibilityRenderObject::headingLevel(renderer->parent()->node()); - - if (parentHeadingLevel) - [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range]; - else - [attrString removeAttribute:@"AXHeadingLevel" range:range]; -} - -static AccessibilityObject* AXLinkElementForNode(Node* node) -{ - RenderObject* obj = node->renderer(); - if (!obj) - return 0; - - RefPtr<AccessibilityObject> axObj = obj->document()->axObjectCache()->getOrCreate(obj); - Element* anchor = axObj->anchorElement(); - if (!anchor) - return 0; - - RenderObject* anchorRenderer = anchor->renderer(); - if (!anchorRenderer) - return 0; - - return anchorRenderer->document()->axObjectCache()->getOrCreate(anchorRenderer); -} - -static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range) -{ - if (object && object->isAccessibilityRenderObject()) { - // make a serialiazable AX object - - RenderObject* renderer = static_cast<AccessibilityRenderObject*>(object)->renderer(); - if (!renderer) - return; - - Document* doc = renderer->document(); - if (!doc) - return; - - AXObjectCache* cache = doc->axObjectCache(); - if (!cache) - return; - - AXUIElementRef axElement = [[WebCoreViewFactory sharedFactory] AXUIElementForElement:object->wrapper()]; - if (axElement) { - [attrString addAttribute:attribute value:(id)axElement range:range]; - CFRelease(axElement); - } - } else - [attrString removeAttribute:attribute range:range]; -} - -static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, int offset, const UChar* chars, int length) -{ - // skip invisible text - if (!node->renderer()) - return; - - // easier to calculate the range before appending the string - NSRange attrStringRange = NSMakeRange([attrString length], length); - - // append the string from this node - [[attrString mutableString] appendString:[NSString stringWithCharacters:chars length:length]]; - - // add new attributes and remove irrelevant inherited ones - // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge - // identical colors. Workaround is to not replace an existing color attribute if it matches what we are adding. This also means - // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually. - - // remove inherited attachment from prior AXAttributedStringAppendReplaced - [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange]; - - // set new attributes - AXAttributeStringSetStyle(attrString, node->renderer(), attrStringRange); - AXAttributeStringSetHeadingLevel(attrString, node->renderer(), attrStringRange); - AXAttributeStringSetBlockquoteLevel(attrString, node->renderer(), attrStringRange); - AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AXLinkElementForNode(node), attrStringRange); - - // do spelling last because it tends to break up the range - AXAttributeStringSetSpelling(attrString, node, offset, attrStringRange); -} - -static NSString* nsStringForReplacedNode(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()) { - ASSERT_NOT_REACHED(); - return nil; - } - - // create an AX object, but skip it if it is not supposed to be seen - RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer()); - if (obj->accessibilityIsIgnored()) - return nil; - - // use the attachmentCharacter to represent the replaced node - const UniChar attachmentChar = NSAttachmentCharacter; - return [NSString stringWithCharacters:&attachmentChar length:1]; -} - -- (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(WebCoreTextMarkerRange*)textMarkerRange -{ - // extract the start and end VisiblePosition - VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(textMarkerRange); - if (startVisiblePosition.isNull()) - return nil; - - VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(textMarkerRange); - if (endVisiblePosition.isNull()) - return nil; - - // iterate over the range to build the AX attributed string - NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init]; - TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get()); - while (!it.atEnd()) { - // locate the node and starting offset for this range - int exception = 0; - Node* node = it.range()->startContainer(exception); - ASSERT(node == it.range()->endContainer(exception)); - int offset = it.range()->startOffset(exception); - - // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX) - if (it.length() != 0) { - AXAttributedStringAppendText(attrString, node, offset, it.characters(), it.length()); - } else { - Node* replacedNode = node->childNode(offset); - NSString *attachmentString = nsStringForReplacedNode(replacedNode); - if (attachmentString) { - NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]); - - // append the placeholder string - [[attrString mutableString] appendString:attachmentString]; - - // remove all inherited attributes - [attrString setAttributes:nil range:attrStringRange]; - - // add the attachment attribute - AccessibilityObject* obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer()); - AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange); - } - } - it.advance(); - } - - return [attrString autorelease]; -} - -static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePosition startPosition, VisiblePosition endPosition) -{ - WebCoreTextMarker* startTextMarker = textMarkerForVisiblePosition(startPosition); - WebCoreTextMarker* endTextMarker = textMarkerForVisiblePosition(endPosition); - return textMarkerRangeFromMarkers(startTextMarker, endTextMarker); -} - -- (NSArray*)accessibilityActionNames -{ - if (!m_object) - return nil; - - m_object->updateBackingStore(); - - static NSArray* actionElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityPressAction, NSAccessibilityShowMenuAction, nil]; - static NSArray* defaultElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityShowMenuAction, nil]; - static NSArray* menuElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityCancelAction, NSAccessibilityPressAction, nil]; - - NSArray *actions; - if (m_object->actionElement()) - actions = actionElementActions; - else if (m_object->isMenuRelated()) - actions = menuElementActions; - else if (m_object->isAttachment()) - actions = [[self attachmentView] accessibilityActionNames]; - else - actions = defaultElementActions; - - return actions; -} - -- (NSArray*)accessibilityAttributeNames -{ - if (!m_object) - return nil; - - m_object->updateBackingStore(); - - if (m_object->isAttachment()) - return [[self attachmentView] accessibilityAttributeNames]; - - static NSArray* attributes = nil; - static NSArray* anchorAttrs = nil; - static NSArray* webAreaAttrs = nil; - static NSArray* textAttrs = nil; - static NSArray* listBoxAttrs = nil; - static NSArray* rangeAttrs = nil; - static NSArray* commonMenuAttrs = nil; - static NSArray* menuAttrs = nil; - static NSArray* menuBarAttrs = nil; - static NSArray* menuItemAttrs = nil; - static NSArray* menuButtonAttrs = nil; - static NSArray* controlAttrs = nil; - static NSArray* tableAttrs = nil; - static NSArray* tableRowAttrs = nil; - static NSArray* tableColAttrs = nil; - static NSArray* tableCellAttrs = nil; - static NSArray* groupAttrs = nil; - static NSArray* inputImageAttrs = nil; - NSMutableArray* tempArray; - if (attributes == nil) { - attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute, - NSAccessibilitySubroleAttribute, - NSAccessibilityRoleDescriptionAttribute, - NSAccessibilityChildrenAttribute, - NSAccessibilityHelpAttribute, - NSAccessibilityParentAttribute, - NSAccessibilityPositionAttribute, - NSAccessibilitySizeAttribute, - NSAccessibilityTitleAttribute, - NSAccessibilityDescriptionAttribute, - NSAccessibilityValueAttribute, - NSAccessibilityFocusedAttribute, - NSAccessibilityEnabledAttribute, - NSAccessibilityWindowAttribute, - @"AXSelectedTextMarkerRange", - @"AXStartTextMarker", - @"AXEndTextMarker", - @"AXVisited", - NSAccessibilityLinkedUIElementsAttribute, - NSAccessibilitySelectedAttribute, - NSAccessibilityBlockQuoteLevelAttribute, - NSAccessibilityTopLevelUIElementAttribute, - nil]; - } - if (commonMenuAttrs == nil) { - commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute, - NSAccessibilityRoleDescriptionAttribute, - NSAccessibilityChildrenAttribute, - NSAccessibilityParentAttribute, - NSAccessibilityEnabledAttribute, - NSAccessibilityPositionAttribute, - NSAccessibilitySizeAttribute, - nil]; - } - if (anchorAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:NSAccessibilityURLAttribute]; - [tempArray addObject:NSAccessibilityAccessKeyAttribute]; - anchorAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (webAreaAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:@"AXLinkUIElements"]; - [tempArray addObject:@"AXLoaded"]; - [tempArray addObject:@"AXLayoutCount"]; - [tempArray addObject:NSAccessibilityURLAttribute]; - webAreaAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (textAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute]; - [tempArray addObject:NSAccessibilitySelectedTextAttribute]; - [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute]; - [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute]; - [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute]; - [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; - [tempArray addObject:NSAccessibilityAccessKeyAttribute]; - textAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (listBoxAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:NSAccessibilitySelectedChildrenAttribute]; - [tempArray addObject:NSAccessibilityVisibleChildrenAttribute]; - [tempArray addObject:NSAccessibilityOrientationAttribute]; - [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; - [tempArray addObject:NSAccessibilityAccessKeyAttribute]; - listBoxAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (rangeAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:NSAccessibilityTopLevelUIElementAttribute]; - [tempArray addObject:NSAccessibilityValueAttribute]; - [tempArray addObject:NSAccessibilityMinValueAttribute]; - [tempArray addObject:NSAccessibilityMaxValueAttribute]; - rangeAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (menuBarAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs]; - [tempArray addObject:NSAccessibilitySelectedChildrenAttribute]; - [tempArray addObject:NSAccessibilityVisibleChildrenAttribute]; - [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; - menuBarAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (menuAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs]; - [tempArray addObject:NSAccessibilitySelectedChildrenAttribute]; - [tempArray addObject:NSAccessibilityVisibleChildrenAttribute]; - [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; - menuAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (menuItemAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs]; - [tempArray addObject:NSAccessibilityTitleAttribute]; - [tempArray addObject:NSAccessibilityHelpAttribute]; - [tempArray addObject:NSAccessibilitySelectedAttribute]; - [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute]; - [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute]; - [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute]; - [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute]; - [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute]; - [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute]; - [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute]; - menuItemAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (menuButtonAttrs == nil) { - menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute, - NSAccessibilityRoleDescriptionAttribute, - NSAccessibilityParentAttribute, - NSAccessibilityPositionAttribute, - NSAccessibilitySizeAttribute, - NSAccessibilityWindowAttribute, - NSAccessibilityTopLevelUIElementAttribute, - NSAccessibilityEnabledAttribute, - NSAccessibilityFocusedAttribute, - NSAccessibilityTitleAttribute, - NSAccessibilityChildrenAttribute, nil]; - } - if (controlAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; - [tempArray addObject:NSAccessibilityAccessKeyAttribute]; - controlAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (tableAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:NSAccessibilityRowsAttribute]; - [tempArray addObject:NSAccessibilityVisibleRowsAttribute]; - [tempArray addObject:NSAccessibilityColumnsAttribute]; - [tempArray addObject:NSAccessibilityVisibleColumnsAttribute]; - [tempArray addObject:NSAccessibilityVisibleCellsAttribute]; - [tempArray addObject:(NSString *)kAXColumnHeaderUIElementsAttribute]; - [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute]; - [tempArray addObject:NSAccessibilityHeaderAttribute]; - tableAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (tableRowAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:NSAccessibilityIndexAttribute]; - tableRowAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (tableColAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:NSAccessibilityIndexAttribute]; - [tempArray addObject:NSAccessibilityHeaderAttribute]; - [tempArray addObject:NSAccessibilityRowsAttribute]; - [tempArray addObject:NSAccessibilityVisibleRowsAttribute]; - tableColAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (tableCellAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:NSAccessibilityRowIndexRangeAttribute]; - [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute]; - tableCellAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (groupAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:attributes]; - [tempArray addObject:NSAccessibilityTitleUIElementAttribute]; - groupAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (inputImageAttrs == nil) { - tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs]; - [tempArray addObject:NSAccessibilityURLAttribute]; - [tempArray addObject:NSAccessibilityAccessKeyAttribute]; - inputImageAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - - if (m_object->isPasswordField()) - return attributes; - - if (m_object->isWebArea()) - return webAreaAttrs; - - if (m_object->isTextControl()) - return textAttrs; - - if (m_object->isAnchor() || m_object->isImage()) - return anchorAttrs; - - if (m_object->isDataTable()) - return tableAttrs; - if (m_object->isTableRow()) - return tableRowAttrs; - if (m_object->isTableColumn()) - return tableColAttrs; - if (m_object->isTableCell()) - return tableCellAttrs; - - if (m_object->isListBox() || m_object->isList()) - return listBoxAttrs; - - if (m_object->isProgressIndicator() || m_object->isSlider()) - return rangeAttrs; - - if (m_object->isInputImage()) - return inputImageAttrs; - - if (m_object->isControl()) - return controlAttrs; - - if (m_object->isGroup()) - return groupAttrs; - - if (m_object->isMenu()) - return menuAttrs; - if (m_object->isMenuBar()) - return menuBarAttrs; - if (m_object->isMenuButton()) - return menuButtonAttrs; - if (m_object->isMenuItem()) - return menuItemAttrs; - - return attributes; -} - -- (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(WebCoreTextMarkerRange*) textMarkerRange -{ - return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(textMarkerRange), visiblePositionForEndOfTextMarkerRange(textMarkerRange)); -} - -- (NSArray*)renderWidgetChildren -{ - Widget* widget = m_object->widget(); - if (!widget) - return nil; - return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute]; -} - -static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector) -{ - unsigned length = [array count]; - vector.reserveInitialCapacity(length); - for (unsigned i = 0; i < length; ++i) { - AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject]; - if (obj) - vector.append(obj); - } -} - -static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector) -{ - unsigned length = vector.size(); - NSMutableArray* array = [NSMutableArray arrayWithCapacity: length]; - for (unsigned i = 0; i < length; ++i) { - AccessibilityObjectWrapper* wrapper = vector[i]->wrapper(); - ASSERT(wrapper); - if (wrapper) { - // we want to return the attachment view instead of the object representing the attachment. - // otherwise, we get palindrome errors in the AX hierarchy - if (vector[i]->isAttachment() && [wrapper attachmentView]) - [array addObject:[wrapper attachmentView]]; - else - [array addObject:wrapper]; - } - } - return array; -} - -- (WebCoreTextMarkerRange*)textMarkerRangeForSelection -{ - VisibleSelection selection = m_object->selection(); - if (selection.isNone()) - return nil; - return textMarkerRangeFromVisiblePositions(selection.visibleStart(), selection.visibleEnd()); -} - -- (NSValue*)position -{ - IntRect rect = m_object->elementRect(); - - // The Cocoa accessibility API wants the lower-left corner. - NSPoint point = NSMakePoint(rect.x(), rect.bottom()); - FrameView* frameView = m_object->documentFrameView(); - if (frameView) { - NSView* view = frameView->documentView(); - point = [[view window] convertBaseToScreen: [view convertPoint: point toView:nil]]; - } - - return [NSValue valueWithPoint: point]; -} - -typedef HashMap<int, NSString*> AccessibilityRoleMap; - -static const AccessibilityRoleMap& createAccessibilityRoleMap() -{ - struct RoleEntry { - AccessibilityRole value; - NSString* string; - }; - - static const RoleEntry roles[] = { - { UnknownRole, NSAccessibilityUnknownRole }, - { ButtonRole, NSAccessibilityButtonRole }, - { RadioButtonRole, NSAccessibilityRadioButtonRole }, - { CheckBoxRole, NSAccessibilityCheckBoxRole }, - { SliderRole, NSAccessibilitySliderRole }, - { TabGroupRole, NSAccessibilityTabGroupRole }, - { TextFieldRole, NSAccessibilityTextFieldRole }, - { StaticTextRole, NSAccessibilityStaticTextRole }, - { TextAreaRole, NSAccessibilityTextAreaRole }, - { ScrollAreaRole, NSAccessibilityScrollAreaRole }, - { PopUpButtonRole, NSAccessibilityPopUpButtonRole }, - { MenuButtonRole, NSAccessibilityMenuButtonRole }, - { TableRole, NSAccessibilityTableRole }, - { ApplicationRole, NSAccessibilityApplicationRole }, - { GroupRole, NSAccessibilityGroupRole }, - { RadioGroupRole, NSAccessibilityRadioGroupRole }, - { ListRole, NSAccessibilityListRole }, - { ScrollBarRole, NSAccessibilityScrollBarRole }, - { ValueIndicatorRole, NSAccessibilityValueIndicatorRole }, - { ImageRole, NSAccessibilityImageRole }, - { MenuBarRole, NSAccessibilityMenuBarRole }, - { MenuRole, NSAccessibilityMenuRole }, - { MenuItemRole, NSAccessibilityMenuItemRole }, - { ColumnRole, NSAccessibilityColumnRole }, - { RowRole, NSAccessibilityRowRole }, - { ToolbarRole, NSAccessibilityToolbarRole }, - { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole }, - { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole }, - { WindowRole, NSAccessibilityWindowRole }, - { DrawerRole, NSAccessibilityDrawerRole }, - { SystemWideRole, NSAccessibilitySystemWideRole }, - { OutlineRole, NSAccessibilityOutlineRole }, - { IncrementorRole, NSAccessibilityIncrementorRole }, - { BrowserRole, NSAccessibilityBrowserRole }, - { ComboBoxRole, NSAccessibilityComboBoxRole }, - { SplitGroupRole, NSAccessibilitySplitGroupRole }, - { SplitterRole, NSAccessibilitySplitterRole }, - { ColorWellRole, NSAccessibilityColorWellRole }, - { GrowAreaRole, NSAccessibilityGrowAreaRole }, - { SheetRole, NSAccessibilitySheetRole }, - { HelpTagRole, NSAccessibilityHelpTagRole }, - { MatteRole, NSAccessibilityMatteRole }, - { RulerRole, NSAccessibilityRulerRole }, - { RulerMarkerRole, NSAccessibilityRulerMarkerRole }, - { LinkRole, NSAccessibilityLinkRole }, -#ifndef BUILDING_ON_TIGER - { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole }, - { GridRole, NSAccessibilityGridRole }, -#endif - { WebCoreLinkRole, NSAccessibilityLinkRole }, - { ImageMapLinkRole, NSAccessibilityLinkRole }, - { ImageMapRole, @"AXImageMap" }, - { ListMarkerRole, @"AXListMarker" }, - { WebAreaRole, @"AXWebArea" }, - { HeadingRole, @"AXHeading" }, - { ListBoxRole, NSAccessibilityListRole }, - { ListBoxOptionRole, NSAccessibilityStaticTextRole }, - // cells don't exist on tiger or leopard -#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) - { CellRole, NSAccessibilityGroupRole }, -#else - { CellRole, NSAccessibilityCellRole }, -#endif - { TableHeaderContainerRole, NSAccessibilityGroupRole }, - { DefinitionListDefinitionRole, NSAccessibilityGroupRole }, - { DefinitionListTermRole, NSAccessibilityGroupRole } - - }; - AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap; - - const unsigned numRoles = sizeof(roles) / sizeof(roles[0]); - for (unsigned i = 0; i < numRoles; ++i) - roleMap.set(roles[i].value, roles[i].string); - return roleMap; -} - -static NSString* roleValueToNSString(AccessibilityRole value) -{ - ASSERT(value); - static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap(); - return roleMap.get(value); -} - -- (NSString*)role -{ - if (m_object->isAttachment()) - return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute]; - NSString* string = roleValueToNSString(m_object->roleValue()); - if (string != nil) - return string; - return NSAccessibilityUnknownRole; -} - -- (NSString*)subrole -{ - if (m_object->isPasswordField()) - return NSAccessibilitySecureTextFieldSubrole; - - if (m_object->isAttachment()) { - NSView* attachView = [self attachmentView]; - if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) { - return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute]; - } - } - - if (m_object->isList()) { - AccessibilityList* listObject = static_cast<AccessibilityList*>(m_object); - if (listObject->isUnorderedList() || listObject->isOrderedList()) - return NSAccessibilityContentListSubrole; - if (listObject->isDefinitionList()) - return NSAccessibilityDefinitionListSubrole; - } - - return nil; -} - -- (NSString*)roleDescription -{ - if (!m_object) - return nil; - - // attachments have the AXImage role, but a different subrole - if (m_object->isAttachment()) - return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute]; - - // FIXME 3447564: It would be better to call some AppKit API to get these strings - // (which would be the best way to localize them) - - NSString* axRole = [self role]; - if ([axRole isEqualToString:NSAccessibilityButtonRole]) - return NSAccessibilityRoleDescription(NSAccessibilityButtonRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityPopUpButtonRole]) - return NSAccessibilityRoleDescription(NSAccessibilityPopUpButtonRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityStaticTextRole]) - return NSAccessibilityRoleDescription(NSAccessibilityStaticTextRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityImageRole]) - return NSAccessibilityRoleDescription(NSAccessibilityImageRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityGroupRole]) - return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityCheckBoxRole]) - return NSAccessibilityRoleDescription(NSAccessibilityCheckBoxRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityRadioButtonRole]) - return NSAccessibilityRoleDescription(NSAccessibilityRadioButtonRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityTextFieldRole]) - return NSAccessibilityRoleDescription(NSAccessibilityTextFieldRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityTextAreaRole]) - return NSAccessibilityRoleDescription(NSAccessibilityTextAreaRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityListRole]) - return NSAccessibilityRoleDescription(NSAccessibilityListRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityTableRole]) - return NSAccessibilityRoleDescription(NSAccessibilityTableRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityRowRole]) - return NSAccessibilityRoleDescription(NSAccessibilityRowRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityColumnRole]) - return NSAccessibilityRoleDescription(NSAccessibilityColumnRole, [self subrole]); - - if ([axRole isEqualToString:NSAccessibilityCellRole]) - return NSAccessibilityRoleDescription(NSAccessibilityCellRole, [self subrole]); - - if ([axRole isEqualToString:@"AXWebArea"]) - return AXWebAreaText(); - - if ([axRole isEqualToString:@"AXLink"]) - return AXLinkText(); - - if ([axRole isEqualToString:@"AXListMarker"]) - return AXListMarkerText(); - - if ([axRole isEqualToString:@"AXImageMap"]) - return AXImageMapText(); - - if ([axRole isEqualToString:@"AXHeading"]) - return AXHeadingText(); - - if ([axRole isEqualToString:(NSString*)kAXMenuBarItemRole] || - [axRole isEqualToString:NSAccessibilityMenuRole]) - return nil; - - if ([axRole isEqualToString:NSAccessibilityMenuButtonRole]) - return NSAccessibilityRoleDescription(NSAccessibilityMenuButtonRole, [self subrole]); - - return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil); -} - -// FIXME: split up this function in a better way. -// suggestions: Use a hash table that maps attribute names to function calls, -// or maybe pointers to member functions -- (id)accessibilityAttributeValue:(NSString*)attributeName -{ - if (!m_object) - return nil; - - m_object->updateBackingStore(); - - if ([attributeName isEqualToString: NSAccessibilityRoleAttribute]) - return [self role]; - - if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute]) - return [self subrole]; - - if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute]) - return [self roleDescription]; - - if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) { - if (m_object->isAccessibilityRenderObject()) { - FrameView* fv = static_cast<AccessibilityRenderObject*>(m_object)->frameViewIfRenderView(); - if (fv) - return fv->platformWidget(); - } - - return m_object->parentObjectUnignored()->wrapper(); - } - - if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) { - if (m_object->children().isEmpty()) { - NSArray* children = [self renderWidgetChildren]; - if (children != nil) - return children; - } - return convertToNSArray(m_object->children()); - } - - if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) { - if (m_object->isListBox()) { - AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy; - m_object->selectedChildren(selectedChildrenCopy); - return convertToNSArray(selectedChildrenCopy); - } - return nil; - } - - if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) { - if (m_object->isListBox()) { - AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy; - m_object->visibleChildren(visibleChildrenCopy); - return convertToNSArray(visibleChildrenCopy); - } - else if (m_object->isList()) - return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute]; - - return nil; - } - - - if (m_object->isWebArea()) { - if ([attributeName isEqualToString: @"AXLinkUIElements"]) { - AccessibilityObject::AccessibilityChildrenVector links; - static_cast<AccessibilityRenderObject*>(m_object)->getDocumentLinks(links); - return convertToNSArray(links); - } - if ([attributeName isEqualToString: @"AXLoaded"]) - return [NSNumber numberWithBool: m_object->isLoaded()]; - if ([attributeName isEqualToString: @"AXLayoutCount"]) - return [NSNumber numberWithInt: m_object->layoutCount()]; - } - - if (m_object->isTextControl()) { - if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) { - int length = m_object->textLength(); - if (length < 0) - return nil; - return [NSNumber numberWithUnsignedInt:length]; - } - if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) { - String selectedText = m_object->selectedText(); - if (selectedText.isNull()) - return nil; - return (NSString*)selectedText; - } - if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) { - PlainTextRange textRange = m_object->selectedTextRange(); - if (textRange.isNull()) - return nil; - return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)]; - } - // TODO: Get actual visible range. <rdar://problem/4712101> - if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) - return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())]; - if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) { - // if selectionEnd > 0, then there is selected text and this question should not be answered - if (m_object->isPasswordField() || m_object->selectionEnd() > 0) - return nil; - int lineNumber = m_object->lineForPosition(m_object->visiblePositionForIndex(m_object->selectionStart(), true)); - if (lineNumber < 0) - return nil; - return [NSNumber numberWithInt:lineNumber]; - } - } - - if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) { - KURL url = m_object->url(); - if (url.isNull()) - return nil; - return (NSURL*)url; - } - - if ([attributeName isEqualToString: @"AXVisited"]) - return [NSNumber numberWithBool: m_object->isVisited()]; - - if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) { - if (m_object->isAttachment()) { - if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute]) - return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute]; - } - return m_object->title(); - } - - if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) { - if (m_object->isAttachment()) { - if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute]) - return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute]; - } - return m_object->accessibilityDescription(); - } - - if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) { - if (m_object->isAttachment()) { - if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute]) - return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute]; - } - if (m_object->isProgressIndicator() || m_object->isSlider()) - return [NSNumber numberWithFloat:m_object->valueForRange()]; - if (m_object->hasIntValue()) - return [NSNumber numberWithInt:m_object->intValue()]; - return m_object->stringValue(); - } - - if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute]) - return [NSNumber numberWithFloat:m_object->minValueForRange()]; - - if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute]) - return [NSNumber numberWithFloat:m_object->maxValueForRange()]; - - if ([attributeName isEqualToString: NSAccessibilityHelpAttribute]) - return m_object->helpText(); - - if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) - return [NSNumber numberWithBool: m_object->isFocused()]; - - if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute]) - return [NSNumber numberWithBool: m_object->isEnabled()]; - - if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) { - IntSize s = m_object->size(); - return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())]; - } - - if ([attributeName isEqualToString: NSAccessibilityPositionAttribute]) - return [self position]; - - if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] || - [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) { - FrameView* fv = m_object->documentFrameView(); - if (fv) - return [fv->platformWidget() window]; - return nil; - } - - if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) { - AtomicString accessKey = m_object->accessKey(); - if (accessKey.isNull()) - return nil; - return accessKey; - } - - if (m_object->isDataTable()) { - // TODO: distinguish between visible and non-visible rows - if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || - [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) { - return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->rows()); - } - // TODO: distinguish between visible and non-visible columns - if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] || - [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) { - return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->columns()); - } - - // HTML tables don't support these - if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] || - [attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute] || - [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute]) - return nil; - - if ([attributeName isEqualToString:(NSString *)kAXColumnHeaderUIElementsAttribute]) { - AccessibilityObject::AccessibilityChildrenVector columnHeaders; - static_cast<AccessibilityTable*>(m_object)->columnHeaders(columnHeaders); - return convertToNSArray(columnHeaders); - } - - if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) { - AccessibilityObject* headerContainer = static_cast<AccessibilityTable*>(m_object)->headerContainer(); - if (headerContainer) - return headerContainer->wrapper(); - return nil; - } - - if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) { - AccessibilityObject::AccessibilityChildrenVector rowHeaders; - static_cast<AccessibilityTable*>(m_object)->rowHeaders(rowHeaders); - return convertToNSArray(rowHeaders); - } - - if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) { - AccessibilityObject::AccessibilityChildrenVector cells; - static_cast<AccessibilityTable*>(m_object)->cells(cells); - return convertToNSArray(cells); - } - } - - if (m_object->isTableRow()) { - if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) - return [NSNumber numberWithInt:static_cast<AccessibilityTableRow*>(m_object)->rowIndex()]; - } - - if (m_object->isTableColumn()) { - if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) - return [NSNumber numberWithInt:static_cast<AccessibilityTableColumn*>(m_object)->columnIndex()]; - - // rows attribute for a column is the list of all the elements in that column at each row - if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || - [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) { - return convertToNSArray(static_cast<AccessibilityTableColumn*>(m_object)->children()); - } - if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) { - AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_object)->headerObject(); - if (!header) - return nil; - return header->wrapper(); - } - } - - if (m_object->isTableCell()) { - if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) { - pair<int, int> rowRange; - static_cast<AccessibilityTableCell*>(m_object)->rowIndexRange(rowRange); - return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)]; - } - if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) { - pair<int, int> columnRange; - static_cast<AccessibilityTableCell*>(m_object)->columnIndexRange(columnRange); - return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)]; - } - } - - if ((m_object->isListBox() ||m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute]) - return NSAccessibilityVerticalOrientationValue; - - if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) - return [self textMarkerRangeForSelection]; - - if (m_object->isAccessibilityRenderObject()) { - RenderObject* renderer = static_cast<AccessibilityRenderObject*>(m_object)->renderer(); - if (!renderer) - return nil; - - if ([attributeName isEqualToString: @"AXStartTextMarker"]) - return textMarkerForVisiblePosition(startOfDocument(renderer->document())); - if ([attributeName isEqualToString: @"AXEndTextMarker"]) - return textMarkerForVisiblePosition(endOfDocument(renderer->document())); - - if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute]) - return [NSNumber numberWithInt:blockquoteLevel(renderer)]; - } else { - if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute]) { - AccessibilityObject* parent = m_object->parentObjectUnignored(); - if (!parent) - return [NSNumber numberWithInt:0]; - return [parent->wrapper() accessibilityAttributeValue:NSAccessibilityBlockQuoteLevelAttribute]; - } - } - - if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) { - AccessibilityObject::AccessibilityChildrenVector linkedUIElements; - m_object->linkedUIElements(linkedUIElements); - if (linkedUIElements.size() == 0) - return nil; - return convertToNSArray(linkedUIElements); - } - - if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) - return [NSNumber numberWithBool:m_object->isSelected()]; - - if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) { - AccessibilityObject* uiElement = static_cast<AccessibilityRenderObject*>(m_object)->menuForMenuButton(); - if (uiElement) - return [NSArray arrayWithObject:uiElement->wrapper()]; - } - - if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) { - AccessibilityObject* obj = m_object->titleUIElement(); - if (obj) - return obj->wrapper(); - return nil; - } - - return nil; -} - -- (id)accessibilityFocusedUIElement -{ - if (!m_object) - return nil; - - m_object->updateBackingStore(); - - RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement(); - - if (!focusedObj) - return nil; - - return focusedObj->wrapper(); -} - -- (id)accessibilityHitTest:(NSPoint)point -{ - if (!m_object) - return nil; - - m_object->updateBackingStore(); - - RefPtr<AccessibilityObject> axObject = m_object->doAccessibilityHitTest(IntPoint(point)); - if (axObject) - return NSAccessibilityUnignoredAncestor(axObject->wrapper()); - return NSAccessibilityUnignoredAncestor(self); -} - -- (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName -{ - if (!m_object) - return nil; - - m_object->updateBackingStore(); - - if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) - return YES; - - if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) - return m_object->canSetFocusAttribute(); - - if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) - return m_object->canSetValueAttribute(); - - if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) - return m_object->canSetSelectedAttribute(); - - if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) - return m_object->canSetSelectedChildrenAttribute(); - - if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] || - [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] || - [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) - return m_object->canSetTextRangeAttributes(); - - return NO; -} - -// accessibilityShouldUseUniqueId is an AppKit method we override so that -// objects will be given a unique ID, and therefore allow AppKit to know when they -// become obsolete (e.g. when the user navigates to a new web page, making this one -// unrendered but not deallocated because it is in the back/forward cache). -// It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the -// appropriate place (e.g. dealloc) to remove these non-retained references from -// AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement. -// -// Registering an object is also required for observing notifications. Only registered objects can be observed. -- (BOOL)accessibilityIsIgnored -{ - if (!m_object) - return nil; - - m_object->updateBackingStore(); - - if (m_object->isAttachment()) - return [[self attachmentView] accessibilityIsIgnored]; - return m_object->accessibilityIsIgnored(); -} - -- (NSArray* )accessibilityParameterizedAttributeNames -{ - if (!m_object) - return nil; - - m_object->updateBackingStore(); - - if (m_object->isAttachment()) - return nil; - - static NSArray* paramAttrs = nil; - static NSArray* textParamAttrs = nil; - static NSArray* tableParamAttrs = nil; - if (paramAttrs == nil) { - paramAttrs = [[NSArray alloc] initWithObjects: - @"AXUIElementForTextMarker", - @"AXTextMarkerRangeForUIElement", - @"AXLineForTextMarker", - @"AXTextMarkerRangeForLine", - @"AXStringForTextMarkerRange", - @"AXTextMarkerForPosition", - @"AXBoundsForTextMarkerRange", - @"AXAttributedStringForTextMarkerRange", - @"AXTextMarkerRangeForUnorderedTextMarkers", - @"AXNextTextMarkerForTextMarker", - @"AXPreviousTextMarkerForTextMarker", - @"AXLeftWordTextMarkerRangeForTextMarker", - @"AXRightWordTextMarkerRangeForTextMarker", - @"AXLeftLineTextMarkerRangeForTextMarker", - @"AXRightLineTextMarkerRangeForTextMarker", - @"AXSentenceTextMarkerRangeForTextMarker", - @"AXParagraphTextMarkerRangeForTextMarker", - @"AXNextWordEndTextMarkerForTextMarker", - @"AXPreviousWordStartTextMarkerForTextMarker", - @"AXNextLineEndTextMarkerForTextMarker", - @"AXPreviousLineStartTextMarkerForTextMarker", - @"AXNextSentenceEndTextMarkerForTextMarker", - @"AXPreviousSentenceStartTextMarkerForTextMarker", - @"AXNextParagraphEndTextMarkerForTextMarker", - @"AXPreviousParagraphStartTextMarkerForTextMarker", - @"AXStyleTextMarkerRangeForTextMarker", - @"AXLengthForTextMarkerRange", - NSAccessibilityBoundsForRangeParameterizedAttribute, - nil]; - } - - if (textParamAttrs == nil) { - NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs]; - [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute]; - [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute]; - [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute]; - [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute]; - [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute]; - [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute]; - [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute]; - [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute]; - [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute]; - textParamAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - if (tableParamAttrs == nil) { - NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs]; - [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute]; - tableParamAttrs = [[NSArray alloc] initWithArray:tempArray]; - [tempArray release]; - } - - if (m_object->isPasswordField()) - return [NSArray array]; - - if (!m_object->isAccessibilityRenderObject()) - return paramAttrs; - - if (m_object->isTextControl()) - return textParamAttrs; - - if (m_object->isDataTable()) - return tableParamAttrs; - - if (m_object->isMenuRelated()) - return nil; - - return paramAttrs; -} - -- (void)accessibilityPerformPressAction -{ - if (!m_object) - return; - - m_object->updateBackingStore(); - - if (m_object->isAttachment()) - [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction]; - - m_object->press(); -} - -- (void)accessibilityPerformShowMenuAction -{ - // This needs to be performed in an iteration of the run loop that did not start from an AX call. - // If it's the same run loop iteration, the menu open notification won't be sent - [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0]; -} - -- (void)accessibilityShowContextMenu -{ - FrameView* frameView = m_object->documentFrameView(); - if (!frameView) - return; - - // simulate a click in the middle of the object - IntPoint clickPoint = m_object->clickPoint(); - NSPoint nsClickPoint = NSMakePoint(clickPoint.x(), clickPoint.y()); - - NSView* view = nil; - if (m_object->isAttachment()) - view = [self attachmentView]; - else - view = frameView->documentView(); - - if (!view) - return; - - NSPoint nsScreenPoint = [view convertPoint:nsClickPoint toView:nil]; - - // Show the contextual menu for this event. - NSEvent* event = [NSEvent mouseEventWithType:NSRightMouseDown location:nsScreenPoint modifierFlags:0 timestamp:0 windowNumber:[[view window] windowNumber] context:0 eventNumber:0 clickCount:1 pressure:1]; - NSMenu* menu = [view menuForEvent:event]; - - if (menu) - [NSMenu popUpContextMenu:menu withEvent:event forView:view]; -} - -- (void)accessibilityPerformAction:(NSString*)action -{ - if (!m_object) - return; - - m_object->updateBackingStore(); - - if ([action isEqualToString:NSAccessibilityPressAction]) - [self accessibilityPerformPressAction]; - - else if ([action isEqualToString:NSAccessibilityShowMenuAction]) - [self accessibilityPerformShowMenuAction]; -} - -- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName -{ - if (!m_object) - return; - - m_object->updateBackingStore(); - - WebCoreTextMarkerRange* textMarkerRange = nil; - NSNumber* number = nil; - NSString* string = nil; - NSRange range = {0, 0}; - NSArray* array = nil; - - // decode the parameter - if ([[WebCoreViewFactory sharedFactory] objectIsTextMarkerRange:value]) - textMarkerRange = (WebCoreTextMarkerRange*) value; - - else if ([value isKindOfClass:[NSNumber self]]) - number = value; - - else if ([value isKindOfClass:[NSString self]]) - string = value; - - else if ([value isKindOfClass:[NSValue self]]) - range = [value rangeValue]; - - else if ([value isKindOfClass:[NSArray self]]) - array = value; - - // handle the command - if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) { - ASSERT(textMarkerRange); - m_object->setSelectedVisiblePositionRange([self visiblePositionRangeForTextMarkerRange:textMarkerRange]); - } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) { - ASSERT(number); - m_object->setFocused([number intValue] != 0); - } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) { - if (!string) - return; - m_object->setValue(string); - } else if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) { - if (!number) - return; - m_object->setSelected([number boolValue]); - } else if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) { - if (!array || m_object->roleValue() != ListBoxRole) - return; - AccessibilityObject::AccessibilityChildrenVector selectedChildren; - convertToVector(array, selectedChildren); - static_cast<AccessibilityListBox*>(m_object)->setSelectedChildren(selectedChildren); - } else if (m_object->isTextControl()) { - if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) { - m_object->setSelectedText(string); - } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) { - m_object->setSelectedTextRange(PlainTextRange(range.location, range.length)); - } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) { - m_object->makeRangeVisible(PlainTextRange(range.location, range.length)); - } - } -} - -static RenderObject* rendererForView(NSView* view) -{ - if (![view conformsToProtocol:@protocol(WebCoreFrameView)]) - return 0; - - NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view; - Frame* frame = [frameView _web_frame]; - if (!frame) - return 0; - - Node* node = frame->document()->ownerElement(); - if (!node) - return 0; - - return node->renderer(); -} - -- (id)_accessibilityParentForSubview:(NSView*)subview -{ - RenderObject* renderer = rendererForView(subview); - if (!renderer) - return nil; - - AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer); - if (obj) - return obj->parentObjectUnignored()->wrapper(); - return nil; -} - -- (NSString*)accessibilityActionDescription:(NSString*)action -{ - // we have no custom actions - return NSAccessibilityActionDescription(action); -} - -// The CFAttributedStringType representation of the text associated with this accessibility -// object that is specified by the given range. -- (NSAttributedString*)doAXAttributedStringForRange:(NSRange)range -{ - PlainTextRange textRange = PlainTextRange(range.location, range.length); - VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange); - return [self doAXAttributedStringForTextMarkerRange:textMarkerRangeFromVisiblePositions(visiblePosRange.start, visiblePosRange.end)]; -} - -// The RTF representation of the text associated with this accessibility object that is -// specified by the given range. -- (NSData*)doAXRTFForRange:(NSRange)range -{ - NSAttributedString* attrString = [self doAXAttributedStringForRange:range]; - return [attrString RTFFromRange: NSMakeRange(0, [attrString length]) documentAttributes: nil]; -} - -- (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter -{ - WebCoreTextMarker* textMarker = nil; - WebCoreTextMarkerRange* textMarkerRange = nil; - NSNumber* number = nil; - NSArray* array = nil; - RefPtr<AccessibilityObject> uiElement = 0; - NSPoint point = NSZeroPoint; - bool pointSet = false; - NSRange range = {0, 0}; - bool rangeSet = false; - - // basic parameter validation - if (!m_object || !attribute || !parameter) - return nil; - - m_object->updateBackingStore(); - - // common parameter type check/casting. Nil checks in handlers catch wrong type case. - // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from - // a parameter of the wrong type. - if ([[WebCoreViewFactory sharedFactory] objectIsTextMarker:parameter]) - textMarker = (WebCoreTextMarker*) parameter; - - else if ([[WebCoreViewFactory sharedFactory] objectIsTextMarkerRange:parameter]) - textMarkerRange = (WebCoreTextMarkerRange*) parameter; - - else if ([parameter isKindOfClass:[AccessibilityObjectWrapper self]]) - uiElement = [(AccessibilityObjectWrapper*)parameter accessibilityObject]; - - else if ([parameter isKindOfClass:[NSNumber self]]) - number = parameter; - - else if ([parameter isKindOfClass:[NSArray self]]) - array = parameter; - - else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSPoint)) == 0) { - pointSet = true; - point = [(NSValue*)parameter pointValue]; - - } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRange)) == 0) { - rangeSet = true; - range = [(NSValue*)parameter rangeValue]; - - } else { - // got a parameter of a type we never use - // NOTE: No ASSERT_NOT_REACHED because this can happen accidentally - // while using accesstool (e.g.), forcing you to start over - return nil; - } - - // Convert values to WebCore types - // FIXME: prepping all of these values as WebCore types is unnecessary in many - // cases. Re-organization of this function or performing the conversion on a - // need basis are possible improvements. - VisiblePosition visiblePos; - if (textMarker) - visiblePos = visiblePositionForTextMarker(textMarker); - int intNumber = [number intValue]; - VisiblePositionRange visiblePosRange; - if (textMarkerRange) - visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange]; - IntPoint webCorePoint = IntPoint(point); - PlainTextRange plainTextRange = PlainTextRange(range.location, range.length); - - // dispatch - if ([attribute isEqualToString: @"AXUIElementForTextMarker"]) - return m_object->accessibilityObjectForPosition(visiblePos)->wrapper(); - - if ([attribute isEqualToString: @"AXTextMarkerRangeForUIElement"]) { - VisiblePositionRange vpRange = uiElement.get()->visiblePositionRange(); - return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); - } - - if ([attribute isEqualToString: @"AXLineForTextMarker"]) - return [NSNumber numberWithUnsignedInt:m_object->lineForPosition(visiblePos)]; - - if ([attribute isEqualToString: @"AXTextMarkerRangeForLine"]) { - VisiblePositionRange vpRange = m_object->visiblePositionRangeForLine(intNumber); - return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); - } - - if ([attribute isEqualToString: @"AXStringForTextMarkerRange"]) - return m_object->stringForVisiblePositionRange(visiblePosRange); - - if ([attribute isEqualToString: @"AXTextMarkerForPosition"]) - return pointSet ? textMarkerForVisiblePosition(m_object->visiblePositionForPoint(webCorePoint)) : nil; - - if ([attribute isEqualToString: @"AXBoundsForTextMarkerRange"]) { - NSRect rect = m_object->boundsForVisiblePositionRange(visiblePosRange); - return [NSValue valueWithRect:rect]; - } - - if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) { - VisiblePosition start = m_object->visiblePositionForIndex(range.location); - VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length); - if (start.isNull() || end.isNull()) - return nil; - NSRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange(start, end)); - return [NSValue valueWithRect:rect]; - } - - if ([attribute isEqualToString: @"AXAttributedStringForTextMarkerRange"]) - return [self doAXAttributedStringForTextMarkerRange:textMarkerRange]; - - if ([attribute isEqualToString: @"AXTextMarkerRangeForUnorderedTextMarkers"]) { - if ([array count] < 2) - return nil; - - WebCoreTextMarker* textMarker1 = (WebCoreTextMarker*) [array objectAtIndex:0]; - WebCoreTextMarker* textMarker2 = (WebCoreTextMarker*) [array objectAtIndex:1]; - if (![[WebCoreViewFactory sharedFactory] objectIsTextMarker:textMarker1] - || ![[WebCoreViewFactory sharedFactory] objectIsTextMarker:textMarker2]) - return nil; - - VisiblePosition visiblePos1 = visiblePositionForTextMarker(textMarker1); - VisiblePosition visiblePos2 = visiblePositionForTextMarker(textMarker2); - VisiblePositionRange vpRange = m_object->visiblePositionRangeForUnorderedPositions(visiblePos1, visiblePos2); - return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); - } - - if ([attribute isEqualToString: @"AXNextTextMarkerForTextMarker"]) - return textMarkerForVisiblePosition(m_object->nextVisiblePosition(visiblePos)); - - if ([attribute isEqualToString: @"AXPreviousTextMarkerForTextMarker"]) - return textMarkerForVisiblePosition(m_object->previousVisiblePosition(visiblePos)); - - if ([attribute isEqualToString: @"AXLeftWordTextMarkerRangeForTextMarker"]) { - VisiblePositionRange vpRange = m_object->positionOfLeftWord(visiblePos); - return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); - } - - if ([attribute isEqualToString: @"AXRightWordTextMarkerRangeForTextMarker"]) { - VisiblePositionRange vpRange = m_object->positionOfRightWord(visiblePos); - return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); - } - - if ([attribute isEqualToString: @"AXLeftLineTextMarkerRangeForTextMarker"]) { - VisiblePositionRange vpRange = m_object->leftLineVisiblePositionRange(visiblePos); - return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); - } - - if ([attribute isEqualToString: @"AXRightLineTextMarkerRangeForTextMarker"]) { - VisiblePositionRange vpRange = m_object->rightLineVisiblePositionRange(visiblePos); - return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); - } - - if ([attribute isEqualToString: @"AXSentenceTextMarkerRangeForTextMarker"]) { - VisiblePositionRange vpRange = m_object->sentenceForPosition(visiblePos); - return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); - } - - if ([attribute isEqualToString: @"AXParagraphTextMarkerRangeForTextMarker"]) { - VisiblePositionRange vpRange = m_object->paragraphForPosition(visiblePos); - return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); - } - - if ([attribute isEqualToString: @"AXNextWordEndTextMarkerForTextMarker"]) - return textMarkerForVisiblePosition(m_object->nextWordEnd(visiblePos)); - - if ([attribute isEqualToString: @"AXPreviousWordStartTextMarkerForTextMarker"]) - return textMarkerForVisiblePosition(m_object->previousWordStart(visiblePos)); - - if ([attribute isEqualToString: @"AXNextLineEndTextMarkerForTextMarker"]) - return textMarkerForVisiblePosition(m_object->nextLineEndPosition(visiblePos)); - - if ([attribute isEqualToString: @"AXPreviousLineStartTextMarkerForTextMarker"]) - return textMarkerForVisiblePosition(m_object->previousLineStartPosition(visiblePos)); - - if ([attribute isEqualToString: @"AXNextSentenceEndTextMarkerForTextMarker"]) - return textMarkerForVisiblePosition(m_object->nextSentenceEndPosition(visiblePos)); - - if ([attribute isEqualToString: @"AXPreviousSentenceStartTextMarkerForTextMarker"]) - return textMarkerForVisiblePosition(m_object->previousSentenceStartPosition(visiblePos)); - - if ([attribute isEqualToString: @"AXNextParagraphEndTextMarkerForTextMarker"]) - return textMarkerForVisiblePosition(m_object->nextParagraphEndPosition(visiblePos)); - - if ([attribute isEqualToString: @"AXPreviousParagraphStartTextMarkerForTextMarker"]) - return textMarkerForVisiblePosition(m_object->previousParagraphStartPosition(visiblePos)); - - if ([attribute isEqualToString: @"AXStyleTextMarkerRangeForTextMarker"]) { - VisiblePositionRange vpRange = m_object->styleRangeForPosition(visiblePos); - return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end); - } - - if ([attribute isEqualToString: @"AXLengthForTextMarkerRange"]) { - int length = m_object->lengthForVisiblePositionRange(visiblePosRange); - if (length < 0) - return nil; - return [NSNumber numberWithInt:length]; - } - - if (m_object->isDataTable()) { - if ([attribute isEqualToString:NSAccessibilityCellForColumnAndRowParameterizedAttribute]) { - if (array == nil || [array count] != 2) - return nil; - AccessibilityTableCell* cell = static_cast<AccessibilityTable*>(m_object)->cellForColumnAndRow([[array objectAtIndex:0] unsignedIntValue], [[array objectAtIndex:1] unsignedIntValue]); - if (!cell) - return nil; - - return cell->wrapper(); - } - } - - if (m_object->isTextControl()) { - if ([attribute isEqualToString: (NSString *)kAXLineForIndexParameterizedAttribute]) { - int lineNumber = m_object->doAXLineForIndex(intNumber); - if (lineNumber < 0) - return nil; - return [NSNumber numberWithUnsignedInt:lineNumber]; - } - - if ([attribute isEqualToString: (NSString *)kAXRangeForLineParameterizedAttribute]) { - PlainTextRange textRange = m_object->doAXRangeForLine(intNumber); - return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)]; - } - - if ([attribute isEqualToString: (NSString*)kAXStringForRangeParameterizedAttribute]) - return rangeSet ? (id)(m_object->doAXStringForRange(plainTextRange)) : nil; - - if ([attribute isEqualToString: (NSString*)kAXRangeForPositionParameterizedAttribute]) { - if (!pointSet) - return nil; - PlainTextRange textRange = m_object->doAXRangeForPosition(webCorePoint); - return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)]; - } - - if ([attribute isEqualToString: (NSString*)kAXRangeForIndexParameterizedAttribute]) { - PlainTextRange textRange = m_object->doAXRangeForIndex(intNumber); - return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)]; - } - - if ([attribute isEqualToString: (NSString*)kAXBoundsForRangeParameterizedAttribute]) { - if (!rangeSet) - return nil; - NSRect rect = m_object->doAXBoundsForRange(plainTextRange); - return [NSValue valueWithRect:rect]; - } - - if ([attribute isEqualToString: (NSString*)kAXRTFForRangeParameterizedAttribute]) - return rangeSet ? [self doAXRTFForRange:range] : nil; - - if ([attribute isEqualToString: (NSString*)kAXAttributedStringForRangeParameterizedAttribute]) - return rangeSet ? [self doAXAttributedStringForRange:range] : nil; - - if ([attribute isEqualToString: (NSString*)kAXStyleRangeForIndexParameterizedAttribute]) { - PlainTextRange textRange = m_object->doAXStyleRangeForIndex(intNumber); - return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)]; - } - } - - return nil; -} - -- (BOOL)accessibilityShouldUseUniqueId -{ - return m_object->accessibilityShouldUseUniqueId(); -} - -// API that AppKit uses for faster access -- (NSUInteger)accessibilityIndexOfChild:(id)child -{ - if (!m_object) - return NSNotFound; - - m_object->updateBackingStore(); - - const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children(); - - if (children.isEmpty()) - return [[self renderWidgetChildren] indexOfObject:child]; - - unsigned count = children.size(); - for (unsigned k = 0; k < count; ++k) { - AccessibilityObjectWrapper* wrapper = children[k]->wrapper(); - if (wrapper == child || (children[k]->isAttachment() && [wrapper attachmentView] == child)) - return k; - } - - return NSNotFound; -} - -- (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute -{ - if (!m_object) - return 0; - - m_object->updateBackingStore(); - - if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { - const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children(); - if (children.isEmpty()) - return [[self renderWidgetChildren] count]; - - return children.size(); - } - - return [super accessibilityArrayAttributeCount:attribute]; -} - -- (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount -{ - if (!m_object) - return nil; - - m_object->updateBackingStore(); - - if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { - if (m_object->children().isEmpty()) { - NSArray *children = [self renderWidgetChildren]; - if (!children) - return nil; - - NSUInteger childCount = [children count]; - if (index >= childCount) - return nil; - - NSUInteger arrayLength = min(childCount - index, maxCount); - return [children subarrayWithRange:NSMakeRange(index, arrayLength)]; - } - - const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children(); - unsigned childCount = children.size(); - if (index >= childCount) - return nil; - - unsigned available = min(childCount - index, maxCount); - - NSMutableArray *subarray = [NSMutableArray arrayWithCapacity:available]; - for (unsigned added = 0; added < available; ++index, ++added) { - AccessibilityObjectWrapper* wrapper = children[index]->wrapper(); - if (wrapper) { - // The attachment view should be returned, otherwise AX palindrome errors occur. - if (children[index]->isAttachment() && [wrapper attachmentView]) - [subarray addObject:[wrapper attachmentView]]; - else - [subarray addObject:wrapper]; - } - } - - return subarray; - } - - return [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount]; -} - -@end - -#endif // HAVE(ACCESSIBILITY) diff --git a/WebCore/page/mac/DragControllerMac.mm b/WebCore/page/mac/DragControllerMac.mm index 86d8f66..c476df7 100644 --- a/WebCore/page/mac/DragControllerMac.mm +++ b/WebCore/page/mac/DragControllerMac.mm @@ -51,11 +51,11 @@ DragOperation DragController::dragOperation(DragData* dragData) ASSERT(dragData); if ([NSApp modalWindow] || !dragData->containsURL()) return DragOperationNone; - - if (!m_document || ![[m_page->mainFrame()->view()->getOuterView() window] attachedSheet] + + if (!m_documentUnderMouse || ![[m_page->mainFrame()->view()->getOuterView() window] attachedSheet] && [dragData->platformData() draggingSource] != m_page->mainFrame()->view()->getOuterView()) return DragOperationCopy; - + return DragOperationNone; } diff --git a/WebCore/page/mac/EventHandlerMac.mm b/WebCore/page/mac/EventHandlerMac.mm index 33d1c5f..d69aff4 100644 --- a/WebCore/page/mac/EventHandlerMac.mm +++ b/WebCore/page/mac/EventHandlerMac.mm @@ -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 @@ -30,6 +30,7 @@ #include "BlockExceptions.h" #include "ChromeClient.h" #include "ClipboardMac.h" +#include "DragController.h" #include "EventNames.h" #include "FocusController.h" #include "FrameLoader.h" @@ -41,15 +42,26 @@ #include "PlatformKeyboardEvent.h" #include "PlatformWheelEvent.h" #include "RenderWidget.h" +#include "RuntimeApplicationChecks.h" #include "Scrollbar.h" #include "Settings.h" +#include <objc/objc-runtime.h> #include <wtf/StdLibExtras.h> +#if !(defined(OBJC_API_VERSION) && OBJC_API_VERSION > 0) +static inline IMP method_setImplementation(Method m, IMP i) +{ + IMP oi = m->method_imp; + m->method_imp = i; + return oi; +} +#endif + namespace WebCore { const double EventHandler::TextDragDelay = 0.15; -static RetainPtr<NSEvent>& currentEvent() +static RetainPtr<NSEvent>& currentNSEventSlot() { DEFINE_STATIC_LOCAL(RetainPtr<NSEvent>, event, ()); return event; @@ -57,19 +69,46 @@ static RetainPtr<NSEvent>& currentEvent() NSEvent *EventHandler::currentNSEvent() { - return currentEvent().get(); + return currentNSEventSlot().get(); +} + +class CurrentEventScope : Noncopyable { +public: + CurrentEventScope(NSEvent *); + ~CurrentEventScope(); + +private: + RetainPtr<NSEvent> m_savedCurrentEvent; +#ifndef NDEBUG + RetainPtr<NSEvent> m_event; +#endif +}; + +inline CurrentEventScope::CurrentEventScope(NSEvent *event) + : m_savedCurrentEvent(currentNSEventSlot()) +#ifndef NDEBUG + , m_event(event) +#endif +{ + currentNSEventSlot() = event; +} + +inline CurrentEventScope::~CurrentEventScope() +{ + ASSERT(currentNSEventSlot() == m_event); + currentNSEventSlot() = m_savedCurrentEvent; } bool EventHandler::wheelEvent(NSEvent *event) { - RetainPtr<NSEvent> oldCurrentEvent = currentEvent(); - currentEvent() = event; + Page* page = m_frame->page(); + if (!page) + return false; - PlatformWheelEvent wheelEvent(event); - handleWheelEvent(wheelEvent); + CurrentEventScope scope(event); - ASSERT(currentEvent() == event); - currentEvent() = oldCurrentEvent; + PlatformWheelEvent wheelEvent(event, page->chrome()->platformWindow()); + handleWheelEvent(wheelEvent); return wheelEvent.isAccepted(); } @@ -131,18 +170,10 @@ bool EventHandler::tabsToAllControls(KeyboardEvent* event) const bool EventHandler::needsKeyboardEventDisambiguationQuirks() const { - static BOOL checkedSafari = NO; - static BOOL isSafari = NO; - - if (!checkedSafari) { - isSafari = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.Safari"]; - checkedSafari = YES; - } - Document* document = m_frame->document(); // RSS view needs arrow key keypress events. - if (isSafari && document->url().protocolIs("feed") || document->url().protocolIs("feeds")) + if (applicationIsSafari() && document->url().protocolIs("feed") || document->url().protocolIs("feeds")) return true; Settings* settings = m_frame->settings(); if (!settings) @@ -161,20 +192,12 @@ bool EventHandler::needsKeyboardEventDisambiguationQuirks() const bool EventHandler::keyEvent(NSEvent *event) { - bool result; BEGIN_BLOCK_OBJC_EXCEPTIONS; ASSERT([event type] == NSKeyDown || [event type] == NSKeyUp); - RetainPtr<NSEvent> oldCurrentEvent = currentEvent(); - currentEvent() = event; - - result = keyEvent(PlatformKeyboardEvent(event)); - - ASSERT(currentEvent() == event); - currentEvent() = oldCurrentEvent; - - return result; + CurrentEventScope scope(event); + return keyEvent(PlatformKeyboardEvent(event)); END_BLOCK_OBJC_EXCEPTIONS; @@ -216,17 +239,17 @@ bool EventHandler::passWidgetMouseDownEventToWidget(RenderWidget* renderWidget) static bool lastEventIsMouseUp() { - // Many AK widgets run their own event loops and consume events while the mouse is down. - // When they finish, currentEvent is the mouseUp that they exited on. We need to update - // the khtml state with this mouseUp, which khtml never saw. This method lets us detect - // that state. + // Many AppKit widgets run their own event loops and consume events while the mouse is down. + // When they finish, currentEvent is the mouseUp that they exited on. We need to update + // the WebCore state with this mouseUp, which we never saw. This method lets us detect + // that state. Handling this was critical when we used AppKit widgets for form elements. + // It's not clear in what cases this is helpful now -- it's possible it can be removed. BEGIN_BLOCK_OBJC_EXCEPTIONS; NSEvent *currentEventAfterHandlingMouseDown = [NSApp currentEvent]; - if (currentEvent() != currentEventAfterHandlingMouseDown && - [currentEventAfterHandlingMouseDown type] == NSLeftMouseUp && - [currentEventAfterHandlingMouseDown timestamp] >= [currentEvent().get() timestamp]) - return true; + return EventHandler::currentNSEvent() != currentEventAfterHandlingMouseDown + && [currentEventAfterHandlingMouseDown type] == NSLeftMouseUp + && [currentEventAfterHandlingMouseDown timestamp] >= [EventHandler::currentNSEvent() timestamp]; END_BLOCK_OBJC_EXCEPTIONS; return false; @@ -234,7 +257,8 @@ static bool lastEventIsMouseUp() bool EventHandler::passMouseDownEventToWidget(Widget* widget) { - // FIXME: this method always returns true + // FIXME: This function always returns true. It should be changed either to return + // false in some cases or the return value should be removed. if (!widget) { LOG_ERROR("hit a RenderWidget without a corresponding Widget, means a frame is half-constructed"); @@ -246,7 +270,7 @@ bool EventHandler::passMouseDownEventToWidget(Widget* widget) NSView *nodeView = widget->platformWidget(); ASSERT(nodeView); ASSERT([nodeView superview]); - NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:[currentEvent().get() locationInWindow] fromView:nil]]; + NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:[currentNSEvent() locationInWindow] fromView:nil]]; if (!view) { // We probably hit the border of a RenderWidget return true; @@ -259,7 +283,7 @@ bool EventHandler::passMouseDownEventToWidget(Widget* widget) if (page->chrome()->client()->firstResponder() != view) { // Normally [NSWindow sendEvent:] handles setting the first responder. // But in our case, the event was sent to the view representing the entire web page. - if ([currentEvent().get() clickCount] <= 1 && [view acceptsFirstResponder] && [view needsPanelToBecomeKey]) + if ([currentNSEvent() clickCount] <= 1 && [view acceptsFirstResponder] && [view needsPanelToBecomeKey]) page->chrome()->client()->makeFirstResponder(view); } @@ -276,7 +300,7 @@ bool EventHandler::passMouseDownEventToWidget(Widget* widget) ASSERT(!m_sendingEventToSubview); m_sendingEventToSubview = true; - [view mouseDown:currentEvent().get()]; + [view mouseDown:currentNSEvent()]; m_sendingEventToSubview = false; if (!wasDeferringLoading) @@ -348,9 +372,10 @@ bool EventHandler::eventLoopHandleMouseDragged(const MouseEventWithHitTestResult return false; if (!m_mouseDownWasInSubframe) { + ASSERT(!m_sendingEventToSubview); m_sendingEventToSubview = true; BEGIN_BLOCK_OBJC_EXCEPTIONS; - [view mouseDragged:currentEvent().get()]; + [view mouseDragged:currentNSEvent()]; END_BLOCK_OBJC_EXCEPTIONS; m_sendingEventToSubview = false; } @@ -374,9 +399,10 @@ bool EventHandler::eventLoopHandleMouseUp(const MouseEventWithHitTestResults&) return false; if (!m_mouseDownWasInSubframe) { + ASSERT(!m_sendingEventToSubview); m_sendingEventToSubview = true; BEGIN_BLOCK_OBJC_EXCEPTIONS; - [view mouseUp:currentEvent().get()]; + [view mouseUp:currentNSEvent()]; END_BLOCK_OBJC_EXCEPTIONS; m_sendingEventToSubview = false; } @@ -388,12 +414,24 @@ bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults& eve { BEGIN_BLOCK_OBJC_EXCEPTIONS; - switch ([currentEvent().get() type]) { + switch ([currentNSEvent() type]) { + case NSLeftMouseDragged: + case NSOtherMouseDragged: + case NSRightMouseDragged: + // This check is bogus and results in <rdar://6813830>, but removing it breaks a number of + // layout tests. + if (!m_mouseDownWasInSubframe) + return false; + if (subframe->page()->dragController()->didInitiateDrag()) + return false; case NSMouseMoved: - // Since we're passing in currentEvent() here, we can call + // Since we're passing in currentNSEvent() here, we can call // handleMouseMoveEvent() directly, since the save/restore of - // currentEvent() that mouseMoved() does would have no effect. - subframe->eventHandler()->handleMouseMoveEvent(currentEvent().get(), hoveredNode); + // currentNSEvent() that mouseMoved() does would have no effect. + ASSERT(!m_sendingEventToSubview); + m_sendingEventToSubview = true; + subframe->eventHandler()->handleMouseMoveEvent(currentPlatformMouseEvent(), hoveredNode); + m_sendingEventToSubview = false; return true; case NSLeftMouseDown: { @@ -414,24 +452,9 @@ bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults& eve case NSLeftMouseUp: { if (!m_mouseDownWasInSubframe) return false; - NSView *view = mouseDownViewIfStillGood(); - if (!view) - return false; ASSERT(!m_sendingEventToSubview); m_sendingEventToSubview = true; - [view mouseUp:currentEvent().get()]; - m_sendingEventToSubview = false; - return true; - } - case NSLeftMouseDragged: { - if (!m_mouseDownWasInSubframe) - return false; - NSView *view = mouseDownViewIfStillGood(); - if (!view) - return false; - ASSERT(!m_sendingEventToSubview); - m_sendingEventToSubview = true; - [view mouseDragged:currentEvent().get()]; + subframe->eventHandler()->handleMouseReleaseEvent(currentPlatformMouseEvent()); m_sendingEventToSubview = false; return true; } @@ -443,23 +466,63 @@ bool EventHandler::passSubframeEventToSubframe(MouseEventWithHitTestResults& eve return false; } +static IMP originalNSScrollViewScrollWheel; +static bool _nsScrollViewScrollWheelShouldRetainSelf; +static void selfRetainingNSScrollViewScrollWheel(NSScrollView *, SEL, NSEvent *); + +static bool nsScrollViewScrollWheelShouldRetainSelf() +{ + ASSERT(isMainThread()); + + return _nsScrollViewScrollWheelShouldRetainSelf; +} + +static void setNSScrollViewScrollWheelShouldRetainSelf(bool shouldRetain) +{ + ASSERT(isMainThread()); + + if (!originalNSScrollViewScrollWheel) { + Method method = class_getInstanceMethod(objc_getRequiredClass("NSScrollView"), @selector(scrollWheel:)); + originalNSScrollViewScrollWheel = method_setImplementation(method, reinterpret_cast<IMP>(selfRetainingNSScrollViewScrollWheel)); + } + + _nsScrollViewScrollWheelShouldRetainSelf = shouldRetain; +} + +static void selfRetainingNSScrollViewScrollWheel(NSScrollView *self, SEL selector, NSEvent *event) +{ + bool shouldRetainSelf = isMainThread() && nsScrollViewScrollWheelShouldRetainSelf(); + + if (shouldRetainSelf) + [self retain]; + originalNSScrollViewScrollWheel(self, selector, event); + if (shouldRetainSelf) + [self release]; +} + bool EventHandler::passWheelEventToWidget(PlatformWheelEvent&, Widget* widget) { BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([currentEvent().get() type] != NSScrollWheel || m_sendingEventToSubview || !widget) + if ([currentNSEvent() type] != NSScrollWheel || m_sendingEventToSubview || !widget) return false; NSView* nodeView = widget->platformWidget(); ASSERT(nodeView); ASSERT([nodeView superview]); - NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:[currentEvent().get() locationInWindow] fromView:nil]]; + NSView *view = [nodeView hitTest:[[nodeView superview] convertPoint:[currentNSEvent() locationInWindow] fromView:nil]]; if (!view) // We probably hit the border of a RenderWidget return false; + ASSERT(!m_sendingEventToSubview); m_sendingEventToSubview = true; - [view scrollWheel:currentEvent().get()]; + // Work around <rdar://problem/6806810> which can cause -[NSScrollView scrollWheel:] to + // crash if the NSScrollView is released during timer or network callback dispatch + // in the nested tracking runloop that -[NSScrollView scrollWheel:] runs. + setNSScrollViewScrollWheelShouldRetainSelf(true); + [view scrollWheel:currentNSEvent()]; + setNSScrollViewScrollWheelShouldRetainSelf(false); m_sendingEventToSubview = false; return true; @@ -479,14 +542,9 @@ void EventHandler::mouseDown(NSEvent *event) m_mouseDownView = nil; - RetainPtr<NSEvent> oldCurrentEvent = currentEvent(); - currentEvent() = event; - m_mouseDown = PlatformMouseEvent(event); - - handleMousePressEvent(event); - - ASSERT(currentEvent() == event); - currentEvent() = oldCurrentEvent; + CurrentEventScope scope(event); + m_mouseDown = currentPlatformMouseEvent(); + handleMousePressEvent(m_mouseDown); END_BLOCK_OBJC_EXCEPTIONS; } @@ -499,13 +557,8 @@ void EventHandler::mouseDragged(NSEvent *event) BEGIN_BLOCK_OBJC_EXCEPTIONS; - RetainPtr<NSEvent> oldCurrentEvent = currentEvent(); - currentEvent() = event; - - handleMouseMoveEvent(event); - - ASSERT(currentEvent() == event); - currentEvent() = oldCurrentEvent; + CurrentEventScope scope(event); + handleMouseMoveEvent(currentPlatformMouseEvent()); END_BLOCK_OBJC_EXCEPTIONS; } @@ -518,8 +571,7 @@ void EventHandler::mouseUp(NSEvent *event) BEGIN_BLOCK_OBJC_EXCEPTIONS; - RetainPtr<NSEvent> oldCurrentEvent = currentEvent(); - currentEvent() = event; + CurrentEventScope scope(event); // Our behavior here is a little different that Qt. Qt always sends // a mouse release event, even for a double click. To correct problems @@ -530,12 +582,9 @@ void EventHandler::mouseUp(NSEvent *event) // treated as another double click. Hence the "% 2" below. int clickCount = [event clickCount]; if (clickCount > 0 && clickCount % 2 == 0) - handleMouseDoubleClickEvent(event); + handleMouseDoubleClickEvent(currentPlatformMouseEvent()); else - handleMouseReleaseEvent(event); - - ASSERT(currentEvent() == event); - currentEvent() = oldCurrentEvent; + handleMouseReleaseEvent(currentPlatformMouseEvent()); m_mouseDownView = nil; @@ -614,15 +663,8 @@ void EventHandler::mouseMoved(NSEvent *event) return; BEGIN_BLOCK_OBJC_EXCEPTIONS; - - RetainPtr<NSEvent> oldCurrentEvent = currentEvent(); - currentEvent() = event; - - mouseMoved(PlatformMouseEvent(event)); - - ASSERT(currentEvent() == event); - currentEvent() = oldCurrentEvent; - + CurrentEventScope scope(event); + mouseMoved(currentPlatformMouseEvent()); END_BLOCK_OBJC_EXCEPTIONS; } @@ -652,4 +694,28 @@ unsigned EventHandler::accessKeyModifiers() return PlatformKeyboardEvent::CtrlKey | PlatformKeyboardEvent::AltKey; } +PlatformMouseEvent EventHandler::currentPlatformMouseEvent() const +{ + NSView *windowView = nil; + if (Page* page = m_frame->page()) + windowView = page->chrome()->platformWindow(); + return PlatformMouseEvent(currentNSEvent(), windowView); +} + +bool EventHandler::sendContextMenuEvent(NSEvent *event) +{ + Page* page = m_frame->page(); + if (!page) + return false; + return sendContextMenuEvent(PlatformMouseEvent(event, page->chrome()->platformWindow())); +} + +bool EventHandler::eventMayStartDrag(NSEvent *event) +{ + Page* page = m_frame->page(); + if (!page) + return false; + return eventMayStartDrag(PlatformMouseEvent(event, page->chrome()->platformWindow())); +} + } diff --git a/WebCore/page/mac/FrameMac.mm b/WebCore/page/mac/FrameMac.mm index f360511..decbcad 100644 --- a/WebCore/page/mac/FrameMac.mm +++ b/WebCore/page/mac/FrameMac.mm @@ -28,6 +28,7 @@ #import "config.h" #import "Frame.h" +#import "Base64.h" #import "BlockExceptions.h" #import "ColorMac.h" #import "Cursor.h" @@ -57,7 +58,6 @@ #import "visible_units.h" #import <Carbon/Carbon.h> -#import <runtime/JSLock.h> #import <wtf/StdLibExtras.h> #if ENABLE(DASHBOARD_SUPPORT) @@ -70,8 +70,6 @@ using namespace std; -using JSC::JSLock; - namespace WebCore { using namespace HTMLNames; @@ -535,6 +533,22 @@ void Frame::setUserStyleSheetLocation(const KURL& url) { delete m_userStyleSheetLoader; m_userStyleSheetLoader = 0; + + // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them + // synchronously and avoid using a loader. + if (url.protocolIs("data") && url.string().startsWith("data:text/css;charset=utf-8;base64,")) { + const unsigned prefixLength = 35; + Vector<char> encodedData(url.string().length() - prefixLength); + for (unsigned i = prefixLength; i < url.string().length(); ++i) + encodedData[i - prefixLength] = static_cast<char>(url.string()[i]); + + Vector<char> styleSheetAsUTF8; + if (base64Decode(encodedData, styleSheetAsUTF8)) { + m_doc->setUserStyleSheet(String::fromUTF8(styleSheetAsUTF8.data())); + return; + } + } + if (m_doc->docLoader()) m_userStyleSheetLoader = new UserStyleSheetLoader(m_doc, url.string()); } diff --git a/WebCore/page/mac/WebCoreViewFactory.h b/WebCore/page/mac/WebCoreViewFactory.h index 883d586..c18f4d4 100644 --- a/WebCore/page/mac/WebCoreViewFactory.h +++ b/WebCore/page/mac/WebCoreViewFactory.h @@ -83,6 +83,19 @@ - (NSString *)contextMenuItemTagDefaultDirection; - (NSString *)contextMenuItemTagLeftToRight; - (NSString *)contextMenuItemTagRightToLeft; +- (NSString *)contextMenuItemTagCorrectSpellingAutomatically; +- (NSString *)contextMenuItemTagSubstitutionsMenu; +- (NSString *)contextMenuItemTagShowSubstitutions:(bool)show; +- (NSString *)contextMenuItemTagSmartCopyPaste; +- (NSString *)contextMenuItemTagSmartQuotes; +- (NSString *)contextMenuItemTagSmartDashes; +- (NSString *)contextMenuItemTagSmartLinks; +- (NSString *)contextMenuItemTagTextReplacement; +- (NSString *)contextMenuItemTagTransformationsMenu; +- (NSString *)contextMenuItemTagMakeUpperCase; +- (NSString *)contextMenuItemTagMakeLowerCase; +- (NSString *)contextMenuItemTagCapitalize; +- (NSString *)contextMenuItemTagChangeBack:(NSString *)replacedString; - (NSString *)contextMenuItemTagInspectElement; - (NSString *)searchMenuNoRecentSearchesText; diff --git a/WebCore/page/win/AXObjectCacheWin.cpp b/WebCore/page/win/AXObjectCacheWin.cpp deleted file mode 100644 index da30ac5..0000000 --- a/WebCore/page/win/AXObjectCacheWin.cpp +++ /dev/null @@ -1,61 +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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#include "config.h" -#include "AXObjectCache.h" - -#include "AccessibilityObject.h" - -namespace WebCore { - -void AXObjectCache::detachWrapper(AccessibilityObject* obj) -{ - // 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(); -} - -void AXObjectCache::attachWrapper(AccessibilityObject*) -{ - // 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 diff --git a/WebCore/page/win/AccessibilityObjectWin.cpp b/WebCore/page/win/AccessibilityObjectWin.cpp deleted file mode 100644 index 0a386c7..0000000 --- a/WebCore/page/win/AccessibilityObjectWin.cpp +++ /dev/null @@ -1,40 +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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "AccessibilityObject.h" - -#if HAVE(ACCESSIBILITY) - -namespace WebCore { - -bool AccessibilityObject::accessibilityIgnoreAttachment() const -{ - return false; -} - -} // namespace WebCore - -#endif // HAVE(ACCESSIBILITY) diff --git a/WebCore/page/win/AccessibilityObjectWrapperWin.h b/WebCore/page/win/AccessibilityObjectWrapperWin.h deleted file mode 100644 index 779443c..0000000 --- a/WebCore/page/win/AccessibilityObjectWrapperWin.h +++ /dev/null @@ -1,54 +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. - * - * 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 AccessibilityObjectWrapperWin_h -#define AccessibilityObjectWrapperWin_h - -namespace WebCore { - - class AccessibilityObject; - - class AccessibilityObjectWrapper : public IUnknown { - 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; - }; - -} // namespace WebCore - -#endif // AccessibilityObjectWrapperWin_h diff --git a/WebCore/page/win/FrameWin.cpp b/WebCore/page/win/FrameWin.cpp index db55d30..0c1c5b1 100644 --- a/WebCore/page/win/FrameWin.cpp +++ b/WebCore/page/win/FrameWin.cpp @@ -61,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); diff --git a/WebCore/page/wx/AccessibilityObjectWx.cpp b/WebCore/page/wx/AccessibilityObjectWx.cpp deleted file mode 100644 index 1710027..0000000 --- a/WebCore/page/wx/AccessibilityObjectWx.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2008 Apple Ltd. - * - * 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 "AccessibilityObject.h" - -#if HAVE(ACCESSIBILITY) - -namespace WebCore { - -bool AccessibilityObject::accessibilityIgnoreAttachment() const -{ - return false; -} - -} // namespace WebCore - -#endif // HAVE(ACCESSIBILITY) |