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

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

Issue 1970653003: ExternalPopupMenu should recreate its popup only if a SELECT subtree is updated (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add an enum argument to updateFromElement 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 867 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 919
917 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) 920 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex)
918 { 921 {
919 m_suggestedIndex = suggestedIndex; 922 m_suggestedIndex = suggestedIndex;
920 923
921 if (LayoutObject* layoutObject = this->layoutObject()) { 924 if (LayoutObject* layoutObject = this->layoutObject()) {
922 layoutObject->updateFromElement(); 925 layoutObject->updateFromElement();
923 scrollToOption(item(listToOptionIndex(suggestedIndex))); 926 scrollToOption(item(listToOptionIndex(suggestedIndex)));
924 } 927 }
925 if (popupIsVisible()) 928 if (popupIsVisible())
926 m_popup->updateFromElement(); 929 m_popup->updateFromElement(PopupMenu::BySelectionChange);
927 } 930 }
928 931
929 void HTMLSelectElement::scrollToOption(HTMLOptionElement* option) 932 void HTMLSelectElement::scrollToOption(HTMLOptionElement* option)
930 { 933 {
931 if (!option) 934 if (!option)
932 return; 935 return;
933 if (usesMenuList()) 936 if (usesMenuList())
934 return; 937 return;
935 bool hasPendingTask = m_optionToScrollTo; 938 bool hasPendingTask = m_optionToScrollTo;
936 // We'd like to keep an HTMLOptionElement reference rather than the index of 939 // 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
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(PopupMenu::BySelectionChange);
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
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
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
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(PopupMenu::ByStyleChange);
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->updateFromElement(PopupMenu::ByDOMChange);
2069 }
2070
1997 } // namespace blink 2071 } // 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