Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(445)

Side by Side Diff: third_party/WebKit/Source/core/html/HTMLSelectElement.cpp

Issue 1972243003: Merge "ExternalPopupMenu should recreate its popup only if a SELECT subtree is updated" to M51 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2704
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 869 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 921
919 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) 922 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex)
920 { 923 {
921 m_suggestedIndex = suggestedIndex; 924 m_suggestedIndex = suggestedIndex;
922 925
923 if (LayoutObject* layoutObject = this->layoutObject()) { 926 if (LayoutObject* layoutObject = this->layoutObject()) {
924 layoutObject->updateFromElement(); 927 layoutObject->updateFromElement();
925 scrollToOption(item(listToOptionIndex(suggestedIndex))); 928 scrollToOption(item(listToOptionIndex(suggestedIndex)));
926 } 929 }
927 if (popupIsVisible()) 930 if (popupIsVisible())
928 m_popup->updateFromElement(); 931 m_popup->updateFromElement(PopupMenu::BySelectionChange);
929 } 932 }
930 933
931 void HTMLSelectElement::scrollToOption(HTMLOptionElement* option) 934 void HTMLSelectElement::scrollToOption(HTMLOptionElement* option)
932 { 935 {
933 if (!option) 936 if (!option)
934 return; 937 return;
935 if (usesMenuList()) 938 if (usesMenuList())
936 return; 939 return;
937 bool hasPendingTask = m_optionToScrollTo; 940 bool hasPendingTask = m_optionToScrollTo;
938 // We'd like to keep an HTMLOptionElement reference rather than the index of 941 // We'd like to keep an HTMLOptionElement reference rather than the index of
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1040 setActiveSelectionAnchor(element); 1043 setActiveSelectionAnchor(element);
1041 if (!m_activeSelectionEnd || shouldDeselect) 1044 if (!m_activeSelectionEnd || shouldDeselect)
1042 setActiveSelectionEnd(element); 1045 setActiveSelectionEnd(element);
1043 } 1046 }
1044 1047
1045 // For the menu list case, this is what makes the selected element appear. 1048 // For the menu list case, this is what makes the selected element appear.
1046 if (LayoutObject* layoutObject = this->layoutObject()) 1049 if (LayoutObject* layoutObject = this->layoutObject())
1047 layoutObject->updateFromElement(); 1050 layoutObject->updateFromElement();
1048 // PopupMenu::updateFromElement() posts an O(N) task. 1051 // PopupMenu::updateFromElement() posts an O(N) task.
1049 if (popupIsVisible()) 1052 if (popupIsVisible())
1050 m_popup->updateFromElement(); 1053 m_popup->updateFromElement(PopupMenu::BySelectionChange);
1051 1054
1052 scrollToSelection(); 1055 scrollToSelection();
1053 setNeedsValidityCheck(); 1056 setNeedsValidityCheck();
1054 1057
1055 if (usesMenuList()) { 1058 if (usesMenuList()) {
1056 if (flags & DispatchInputAndChangeEvent) 1059 if (flags & DispatchInputAndChangeEvent)
1057 dispatchInputAndChangeEventForMenuList(); 1060 dispatchInputAndChangeEventForMenuList();
1058 else 1061 else
1059 m_lastOnChangeOption = element; 1062 m_lastOnChangeOption = element;
1060 if (LayoutObject* layoutObject = this->layoutObject()) { 1063 if (LayoutObject* layoutObject = this->layoutObject()) {
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
1820 } 1823 }
1821 1824
1822 DEFINE_TRACE(HTMLSelectElement) 1825 DEFINE_TRACE(HTMLSelectElement)
1823 { 1826 {
1824 visitor->trace(m_listItems); 1827 visitor->trace(m_listItems);
1825 visitor->trace(m_lastOnChangeOption); 1828 visitor->trace(m_lastOnChangeOption);
1826 visitor->trace(m_activeSelectionAnchor); 1829 visitor->trace(m_activeSelectionAnchor);
1827 visitor->trace(m_activeSelectionEnd); 1830 visitor->trace(m_activeSelectionEnd);
1828 visitor->trace(m_optionToScrollTo); 1831 visitor->trace(m_optionToScrollTo);
1829 visitor->trace(m_popup); 1832 visitor->trace(m_popup);
1833 visitor->trace(m_popupUpdater);
1830 HTMLFormControlElementWithState::trace(visitor); 1834 HTMLFormControlElementWithState::trace(visitor);
1831 } 1835 }
1832 1836
1833 void HTMLSelectElement::didAddUserAgentShadowRoot(ShadowRoot& root) 1837 void HTMLSelectElement::didAddUserAgentShadowRoot(ShadowRoot& root)
1834 { 1838 {
1835 RawPtr<HTMLContentElement> content = HTMLContentElement::create(document()); 1839 RawPtr<HTMLContentElement> content = HTMLContentElement::create(document());
1836 content->setAttribute(selectAttr, "option,optgroup,hr"); 1840 content->setAttribute(selectAttr, "option,optgroup,hr");
1837 root.appendChild(content); 1841 root.appendChild(content);
1838 } 1842 }
1839 1843
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1893 LayoutUnit HTMLSelectElement::clientPaddingRight() const 1897 LayoutUnit HTMLSelectElement::clientPaddingRight() const
1894 { 1898 {
1895 if (layoutObject() && layoutObject()->isMenuList()) 1899 if (layoutObject() && layoutObject()->isMenuList())
1896 return toLayoutMenuList(layoutObject())->clientPaddingRight(); 1900 return toLayoutMenuList(layoutObject())->clientPaddingRight();
1897 return LayoutUnit(); 1901 return LayoutUnit();
1898 } 1902 }
1899 1903
1900 void HTMLSelectElement::popupDidHide() 1904 void HTMLSelectElement::popupDidHide()
1901 { 1905 {
1902 m_popupIsVisible = false; 1906 m_popupIsVisible = false;
1907 unobserveTreeMutation();
1903 if (AXObjectCache* cache = document().existingAXObjectCache()) { 1908 if (AXObjectCache* cache = document().existingAXObjectCache()) {
1904 if (layoutObject() && layoutObject()->isMenuList()) 1909 if (layoutObject() && layoutObject()->isMenuList())
1905 cache->didHideMenuListPopup(toLayoutMenuList(layoutObject())); 1910 cache->didHideMenuListPopup(toLayoutMenuList(layoutObject()));
1906 } 1911 }
1907 } 1912 }
1908 1913
1909 void HTMLSelectElement::setIndexToSelectOnCancel(int listIndex) 1914 void HTMLSelectElement::setIndexToSelectOnCancel(int listIndex)
1910 { 1915 {
1911 m_indexToSelectOnCancel = listIndex; 1916 m_indexToSelectOnCancel = listIndex;
1912 if (layoutObject()) 1917 if (layoutObject())
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1950 if (popupIsVisible()) 1955 if (popupIsVisible())
1951 return; 1956 return;
1952 if (document().frameHost()->chromeClient().hasOpenedPopup()) 1957 if (document().frameHost()->chromeClient().hasOpenedPopup())
1953 return; 1958 return;
1954 if (!layoutObject() || !layoutObject()->isMenuList()) 1959 if (!layoutObject() || !layoutObject()->isMenuList())
1955 return; 1960 return;
1956 1961
1957 if (!m_popup) 1962 if (!m_popup)
1958 m_popup = document().frameHost()->chromeClient().openPopupMenu(*document ().frame(), *this); 1963 m_popup = document().frameHost()->chromeClient().openPopupMenu(*document ().frame(), *this);
1959 m_popupIsVisible = true; 1964 m_popupIsVisible = true;
1965 observeTreeMutation();
1960 1966
1961 LayoutMenuList* menuList = toLayoutMenuList(layoutObject()); 1967 LayoutMenuList* menuList = toLayoutMenuList(layoutObject());
1962 m_popup->show(); 1968 m_popup->show();
1963 if (AXObjectCache* cache = document().existingAXObjectCache()) 1969 if (AXObjectCache* cache = document().existingAXObjectCache())
1964 cache->didShowMenuListPopup(menuList); 1970 cache->didShowMenuListPopup(menuList);
1965 } 1971 }
1966 1972
1967 void HTMLSelectElement::hidePopup() 1973 void HTMLSelectElement::hidePopup()
1968 { 1974 {
1969 if (m_popup) 1975 if (m_popup)
1970 m_popup->hide(); 1976 m_popup->hide();
1971 } 1977 }
1972 1978
1973 void HTMLSelectElement::didRecalcStyle(StyleRecalcChange change) 1979 void HTMLSelectElement::didRecalcStyle(StyleRecalcChange change)
1974 { 1980 {
1975 HTMLFormControlElementWithState::didRecalcStyle(change); 1981 HTMLFormControlElementWithState::didRecalcStyle(change);
1976 if (popupIsVisible()) 1982 if (popupIsVisible())
1977 m_popup->updateFromElement(); 1983 m_popup->updateFromElement(PopupMenu::ByStyleChange);
1978 } 1984 }
1979 1985
1980 void HTMLSelectElement::detach(const AttachContext& context) 1986 void HTMLSelectElement::detach(const AttachContext& context)
1981 { 1987 {
1982 HTMLFormControlElementWithState::detach(context); 1988 HTMLFormControlElementWithState::detach(context);
1983 if (m_popup) 1989 if (m_popup)
1984 m_popup->disconnectClient(); 1990 m_popup->disconnectClient();
1985 m_popupIsVisible = false; 1991 m_popupIsVisible = false;
1986 m_popup = nullptr; 1992 m_popup = nullptr;
1993 unobserveTreeMutation();
1987 } 1994 }
1988 1995
1989 void HTMLSelectElement::resetTypeAheadSessionForTesting() 1996 void HTMLSelectElement::resetTypeAheadSessionForTesting()
1990 { 1997 {
1991 m_typeAhead.resetSession(); 1998 m_typeAhead.resetSession();
1992 } 1999 }
1993 2000
2001 // PopupUpdater notifies updates of the specified SELECT element subtree to
2002 // a PopupMenu object.
2003 class HTMLSelectElement::PopupUpdater : public MutationCallback {
2004 public:
2005 explicit PopupUpdater(HTMLSelectElement&);
2006 DECLARE_VIRTUAL_TRACE();
2007
2008 void dispose()
2009 {
2010 m_observer->disconnect();
2011 }
2012
2013 private:
2014 void call(const HeapVector<Member<MutationRecord>>&, MutationObserver*) over ride
2015 {
2016 m_select->didMutateSubtree();
2017 }
2018
2019 ExecutionContext* getExecutionContext() const override
2020 {
2021 return &m_select->document();
2022 }
2023
2024 Member<HTMLSelectElement> m_select;
2025 Member<MutationObserver> m_observer;
2026 };
2027
2028 HTMLSelectElement::PopupUpdater::PopupUpdater(HTMLSelectElement& select)
2029 : m_select(select)
2030 {
2031 m_observer = MutationObserver::create(this);
2032 MutationObserverInit init;
2033 init.setAttributes(true);
2034 init.setCharacterData(true);
2035 init.setChildList(true);
2036 init.setSubtree(true);
2037 m_observer->observe(&select, init, ASSERT_NO_EXCEPTION);
2038 }
2039
2040 DEFINE_TRACE(HTMLSelectElement::PopupUpdater)
2041 {
2042 visitor->trace(m_select);
2043 visitor->trace(m_observer);
2044 MutationCallback::trace(visitor);
2045 }
2046
2047 void HTMLSelectElement::observeTreeMutation()
2048 {
2049 DCHECK(!m_popupUpdater);
2050 m_popupUpdater = new PopupUpdater(*this);
2051 }
2052
2053 void HTMLSelectElement::unobserveTreeMutation()
2054 {
2055 if (!m_popupUpdater)
2056 return;
2057 m_popupUpdater->dispose();
2058 m_popupUpdater = nullptr;
2059 }
2060
2061 void HTMLSelectElement::didMutateSubtree()
2062 {
2063 DCHECK(popupIsVisible());
2064 DCHECK(m_popup);
2065 m_popup->updateFromElement(PopupMenu::ByDOMChange);
2066 }
2067
1994 } // namespace blink 2068 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLSelectElement.h ('k') | third_party/WebKit/Source/core/loader/EmptyClients.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698