Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). | 2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
| 3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 4 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 4 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 5 * (C) 2001 Dirk Mueller (mueller@kde.org) | 5 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved. |
| 7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 8 * Copyright (C) 2010 Google Inc. All rights reserved. | 8 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) | 9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) |
| 10 * | 10 * |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 | 29 |
| 30 #include "bindings/core/v8/ExceptionMessages.h" | 30 #include "bindings/core/v8/ExceptionMessages.h" |
| 31 #include "bindings/core/v8/ExceptionState.h" | 31 #include "bindings/core/v8/ExceptionState.h" |
| 32 #include "bindings/core/v8/ExceptionStatePlaceholder.h" | 32 #include "bindings/core/v8/ExceptionStatePlaceholder.h" |
| 33 #include "bindings/core/v8/UnionTypesCore.h" | 33 #include "bindings/core/v8/UnionTypesCore.h" |
| 34 #include "core/HTMLNames.h" | 34 #include "core/HTMLNames.h" |
| 35 #include "core/dom/AXObjectCache.h" | 35 #include "core/dom/AXObjectCache.h" |
| 36 #include "core/dom/Attribute.h" | 36 #include "core/dom/Attribute.h" |
| 37 #include "core/dom/ElementTraversal.h" | 37 #include "core/dom/ElementTraversal.h" |
| 38 #include "core/dom/ExecutionContextTask.h" | 38 #include "core/dom/ExecutionContextTask.h" |
| 39 #include "core/dom/MutationCallback.h" | |
| 40 #include "core/dom/MutationObserver.h" | |
| 41 #include "core/dom/MutationObserverInit.h" | |
| 39 #include "core/dom/NodeComputedStyle.h" | 42 #include "core/dom/NodeComputedStyle.h" |
| 40 #include "core/dom/NodeListsNodeData.h" | 43 #include "core/dom/NodeListsNodeData.h" |
| 41 #include "core/dom/NodeTraversal.h" | 44 #include "core/dom/NodeTraversal.h" |
| 42 #include "core/events/GestureEvent.h" | 45 #include "core/events/GestureEvent.h" |
| 43 #include "core/events/KeyboardEvent.h" | 46 #include "core/events/KeyboardEvent.h" |
| 44 #include "core/events/MouseEvent.h" | 47 #include "core/events/MouseEvent.h" |
| 45 #include "core/events/ScopedEventQueue.h" | 48 #include "core/events/ScopedEventQueue.h" |
| 46 #include "core/frame/FrameHost.h" | 49 #include "core/frame/FrameHost.h" |
| 47 #include "core/frame/FrameView.h" | 50 #include "core/frame/FrameView.h" |
| 48 #include "core/frame/LocalFrame.h" | 51 #include "core/frame/LocalFrame.h" |
| (...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1038 setActiveSelectionAnchor(element); | 1041 setActiveSelectionAnchor(element); |
| 1039 if (!m_activeSelectionEnd || shouldDeselect) | 1042 if (!m_activeSelectionEnd || shouldDeselect) |
| 1040 setActiveSelectionEnd(element); | 1043 setActiveSelectionEnd(element); |
| 1041 } | 1044 } |
| 1042 | 1045 |
| 1043 // For the menu list case, this is what makes the selected element appear. | 1046 // For the menu list case, this is what makes the selected element appear. |
| 1044 if (LayoutObject* layoutObject = this->layoutObject()) | 1047 if (LayoutObject* layoutObject = this->layoutObject()) |
| 1045 layoutObject->updateFromElement(); | 1048 layoutObject->updateFromElement(); |
| 1046 // PopupMenu::updateFromElement() posts an O(N) task. | 1049 // PopupMenu::updateFromElement() posts an O(N) task. |
| 1047 if (popupIsVisible()) | 1050 if (popupIsVisible()) |
| 1048 m_popup->updateFromElement(); | 1051 m_popup->updateFromElement(); |
|
keishi
2016/05/11 09:14:41
nit: Maybe selectedness is important enough that w
tkent
2016/05/11 15:56:13
ok, I added an enum argument to updateFromElement
| |
| 1049 | 1052 |
| 1050 scrollToSelection(); | 1053 scrollToSelection(); |
| 1051 setNeedsValidityCheck(); | 1054 setNeedsValidityCheck(); |
| 1052 | 1055 |
| 1053 if (usesMenuList()) { | 1056 if (usesMenuList()) { |
| 1054 if (flags & DispatchInputAndChangeEvent) | 1057 if (flags & DispatchInputAndChangeEvent) |
| 1055 dispatchInputAndChangeEventForMenuList(); | 1058 dispatchInputAndChangeEventForMenuList(); |
| 1056 else | 1059 else |
| 1057 m_lastOnChangeOption = element; | 1060 m_lastOnChangeOption = element; |
| 1058 if (LayoutObject* layoutObject = this->layoutObject()) { | 1061 if (LayoutObject* layoutObject = this->layoutObject()) { |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1818 } | 1821 } |
| 1819 | 1822 |
| 1820 DEFINE_TRACE(HTMLSelectElement) | 1823 DEFINE_TRACE(HTMLSelectElement) |
| 1821 { | 1824 { |
| 1822 visitor->trace(m_listItems); | 1825 visitor->trace(m_listItems); |
| 1823 visitor->trace(m_lastOnChangeOption); | 1826 visitor->trace(m_lastOnChangeOption); |
| 1824 visitor->trace(m_activeSelectionAnchor); | 1827 visitor->trace(m_activeSelectionAnchor); |
| 1825 visitor->trace(m_activeSelectionEnd); | 1828 visitor->trace(m_activeSelectionEnd); |
| 1826 visitor->trace(m_optionToScrollTo); | 1829 visitor->trace(m_optionToScrollTo); |
| 1827 visitor->trace(m_popup); | 1830 visitor->trace(m_popup); |
| 1831 visitor->trace(m_popupUpdater); | |
| 1828 HTMLFormControlElementWithState::trace(visitor); | 1832 HTMLFormControlElementWithState::trace(visitor); |
| 1829 } | 1833 } |
| 1830 | 1834 |
| 1831 void HTMLSelectElement::didAddUserAgentShadowRoot(ShadowRoot& root) | 1835 void HTMLSelectElement::didAddUserAgentShadowRoot(ShadowRoot& root) |
| 1832 { | 1836 { |
| 1833 HTMLContentElement* content = HTMLContentElement::create(document()); | 1837 HTMLContentElement* content = HTMLContentElement::create(document()); |
| 1834 content->setAttribute(selectAttr, "option,optgroup,hr"); | 1838 content->setAttribute(selectAttr, "option,optgroup,hr"); |
| 1835 root.appendChild(content); | 1839 root.appendChild(content); |
| 1836 } | 1840 } |
| 1837 | 1841 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1894 LayoutUnit HTMLSelectElement::clientPaddingRight() const | 1898 LayoutUnit HTMLSelectElement::clientPaddingRight() const |
| 1895 { | 1899 { |
| 1896 if (layoutObject() && layoutObject()->isMenuList()) | 1900 if (layoutObject() && layoutObject()->isMenuList()) |
| 1897 return toLayoutMenuList(layoutObject())->clientPaddingRight(); | 1901 return toLayoutMenuList(layoutObject())->clientPaddingRight(); |
| 1898 return LayoutUnit(); | 1902 return LayoutUnit(); |
| 1899 } | 1903 } |
| 1900 | 1904 |
| 1901 void HTMLSelectElement::popupDidHide() | 1905 void HTMLSelectElement::popupDidHide() |
| 1902 { | 1906 { |
| 1903 m_popupIsVisible = false; | 1907 m_popupIsVisible = false; |
| 1908 unobserveTreeMutation(); | |
| 1904 if (AXObjectCache* cache = document().existingAXObjectCache()) { | 1909 if (AXObjectCache* cache = document().existingAXObjectCache()) { |
| 1905 if (layoutObject() && layoutObject()->isMenuList()) | 1910 if (layoutObject() && layoutObject()->isMenuList()) |
| 1906 cache->didHideMenuListPopup(toLayoutMenuList(layoutObject())); | 1911 cache->didHideMenuListPopup(toLayoutMenuList(layoutObject())); |
| 1907 } | 1912 } |
| 1908 } | 1913 } |
| 1909 | 1914 |
| 1910 void HTMLSelectElement::setIndexToSelectOnCancel(int listIndex) | 1915 void HTMLSelectElement::setIndexToSelectOnCancel(int listIndex) |
| 1911 { | 1916 { |
| 1912 m_indexToSelectOnCancel = listIndex; | 1917 m_indexToSelectOnCancel = listIndex; |
| 1913 if (layoutObject()) | 1918 if (layoutObject()) |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1953 if (document().frameHost()->chromeClient().hasOpenedPopup()) | 1958 if (document().frameHost()->chromeClient().hasOpenedPopup()) |
| 1954 return; | 1959 return; |
| 1955 if (!layoutObject() || !layoutObject()->isMenuList()) | 1960 if (!layoutObject() || !layoutObject()->isMenuList()) |
| 1956 return; | 1961 return; |
| 1957 if (elementRectRelativeToViewport().isEmpty()) | 1962 if (elementRectRelativeToViewport().isEmpty()) |
| 1958 return; | 1963 return; |
| 1959 | 1964 |
| 1960 if (!m_popup) | 1965 if (!m_popup) |
| 1961 m_popup = document().frameHost()->chromeClient().openPopupMenu(*document ().frame(), *this); | 1966 m_popup = document().frameHost()->chromeClient().openPopupMenu(*document ().frame(), *this); |
| 1962 m_popupIsVisible = true; | 1967 m_popupIsVisible = true; |
| 1968 observeTreeMutation(); | |
| 1963 | 1969 |
| 1964 LayoutMenuList* menuList = toLayoutMenuList(layoutObject()); | 1970 LayoutMenuList* menuList = toLayoutMenuList(layoutObject()); |
| 1965 m_popup->show(); | 1971 m_popup->show(); |
| 1966 if (AXObjectCache* cache = document().existingAXObjectCache()) | 1972 if (AXObjectCache* cache = document().existingAXObjectCache()) |
| 1967 cache->didShowMenuListPopup(menuList); | 1973 cache->didShowMenuListPopup(menuList); |
| 1968 } | 1974 } |
| 1969 | 1975 |
| 1970 void HTMLSelectElement::hidePopup() | 1976 void HTMLSelectElement::hidePopup() |
| 1971 { | 1977 { |
| 1972 if (m_popup) | 1978 if (m_popup) |
| 1973 m_popup->hide(); | 1979 m_popup->hide(); |
| 1974 } | 1980 } |
| 1975 | 1981 |
| 1976 void HTMLSelectElement::didRecalcStyle(StyleRecalcChange change) | 1982 void HTMLSelectElement::didRecalcStyle(StyleRecalcChange change) |
| 1977 { | 1983 { |
| 1978 HTMLFormControlElementWithState::didRecalcStyle(change); | 1984 HTMLFormControlElementWithState::didRecalcStyle(change); |
| 1979 if (popupIsVisible()) | 1985 if (popupIsVisible()) |
| 1980 m_popup->updateFromElement(); | 1986 m_popup->updateFromElement(); |
| 1981 } | 1987 } |
| 1982 | 1988 |
| 1983 void HTMLSelectElement::detach(const AttachContext& context) | 1989 void HTMLSelectElement::detach(const AttachContext& context) |
| 1984 { | 1990 { |
| 1985 HTMLFormControlElementWithState::detach(context); | 1991 HTMLFormControlElementWithState::detach(context); |
| 1986 if (m_popup) | 1992 if (m_popup) |
| 1987 m_popup->disconnectClient(); | 1993 m_popup->disconnectClient(); |
| 1988 m_popupIsVisible = false; | 1994 m_popupIsVisible = false; |
| 1989 m_popup = nullptr; | 1995 m_popup = nullptr; |
| 1996 unobserveTreeMutation(); | |
| 1990 } | 1997 } |
| 1991 | 1998 |
| 1992 void HTMLSelectElement::resetTypeAheadSessionForTesting() | 1999 void HTMLSelectElement::resetTypeAheadSessionForTesting() |
| 1993 { | 2000 { |
| 1994 m_typeAhead.resetSession(); | 2001 m_typeAhead.resetSession(); |
| 1995 } | 2002 } |
| 1996 | 2003 |
| 2004 // PopupUpdater notifies updates of the specified SELECT element subtree to | |
| 2005 // a PopupMenu object. | |
| 2006 class HTMLSelectElement::PopupUpdater : public MutationCallback { | |
| 2007 public: | |
| 2008 explicit PopupUpdater(HTMLSelectElement&); | |
| 2009 DECLARE_VIRTUAL_TRACE(); | |
| 2010 | |
| 2011 void dispose() | |
| 2012 { | |
| 2013 m_observer->disconnect(); | |
| 2014 } | |
| 2015 | |
| 2016 private: | |
| 2017 void call(const HeapVector<Member<MutationRecord>>&, MutationObserver*) over ride | |
| 2018 { | |
| 2019 m_select->didMutateSubtree(); | |
| 2020 } | |
| 2021 | |
| 2022 ExecutionContext* getExecutionContext() const override | |
| 2023 { | |
| 2024 return &m_select->document(); | |
| 2025 } | |
| 2026 | |
| 2027 Member<HTMLSelectElement> m_select; | |
| 2028 Member<MutationObserver> m_observer; | |
| 2029 }; | |
| 2030 | |
| 2031 HTMLSelectElement::PopupUpdater::PopupUpdater(HTMLSelectElement& select) | |
| 2032 : m_select(select) | |
| 2033 { | |
| 2034 m_observer = MutationObserver::create(this); | |
| 2035 MutationObserverInit init; | |
| 2036 init.setAttributes(true); | |
| 2037 init.setCharacterData(true); | |
| 2038 init.setChildList(true); | |
| 2039 init.setSubtree(true); | |
| 2040 m_observer->observe(&select, init, ASSERT_NO_EXCEPTION); | |
| 2041 } | |
| 2042 | |
| 2043 DEFINE_TRACE(HTMLSelectElement::PopupUpdater) | |
| 2044 { | |
| 2045 visitor->trace(m_select); | |
| 2046 visitor->trace(m_observer); | |
| 2047 MutationCallback::trace(visitor); | |
| 2048 } | |
| 2049 | |
| 2050 void HTMLSelectElement::observeTreeMutation() | |
| 2051 { | |
| 2052 DCHECK(!m_popupUpdater); | |
| 2053 m_popupUpdater = new PopupUpdater(*this); | |
| 2054 } | |
| 2055 | |
| 2056 void HTMLSelectElement::unobserveTreeMutation() | |
| 2057 { | |
| 2058 if (!m_popupUpdater) | |
| 2059 return; | |
| 2060 m_popupUpdater->dispose(); | |
| 2061 m_popupUpdater = nullptr; | |
| 2062 } | |
| 2063 | |
| 2064 void HTMLSelectElement::didMutateSubtree() | |
| 2065 { | |
| 2066 DCHECK(popupIsVisible()); | |
| 2067 DCHECK(m_popup); | |
| 2068 m_popup->updateFromElementWithMutation(); | |
| 2069 } | |
| 2070 | |
| 1997 } // namespace blink | 2071 } // namespace blink |
| OLD | NEW |