| 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 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 lazyReattachIfAttached(); | 350 lazyReattachIfAttached(); |
| 351 setRecalcListItems(); | 351 setRecalcListItems(); |
| 352 } | 352 } |
| 353 } else if (name == multipleAttr) | 353 } else if (name == multipleAttr) |
| 354 parseMultipleAttribute(value); | 354 parseMultipleAttribute(value); |
| 355 else if (name == accesskeyAttr) { | 355 else if (name == accesskeyAttr) { |
| 356 // FIXME: ignore for the moment. | 356 // FIXME: ignore for the moment. |
| 357 // | 357 // |
| 358 } else if (name == disabledAttr) { | 358 } else if (name == disabledAttr) { |
| 359 HTMLFormControlElementWithState::parseAttribute(name, value); | 359 HTMLFormControlElementWithState::parseAttribute(name, value); |
| 360 if (renderer() && renderer()->isMenuList()) { | 360 if (layoutObject() && layoutObject()->isMenuList()) { |
| 361 if (LayoutMenuList* menuList = toLayoutMenuList(renderer())) { | 361 if (LayoutMenuList* menuList = toLayoutMenuList(layoutObject())) { |
| 362 if (menuList->popupIsVisible()) | 362 if (menuList->popupIsVisible()) |
| 363 menuList->hidePopup(); | 363 menuList->hidePopup(); |
| 364 } | 364 } |
| 365 } | 365 } |
| 366 | 366 |
| 367 } else | 367 } else |
| 368 HTMLFormControlElementWithState::parseAttribute(name, value); | 368 HTMLFormControlElementWithState::parseAttribute(name, value); |
| 369 } | 369 } |
| 370 | 370 |
| 371 bool HTMLSelectElement::shouldShowFocusRingOnMouseFocus() const | 371 bool HTMLSelectElement::shouldShowFocusRingOnMouseFocus() const |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 m_lastOnChangeSelection.clear(); | 411 m_lastOnChangeSelection.clear(); |
| 412 | 412 |
| 413 HTMLFormControlElementWithState::childrenChanged(change); | 413 HTMLFormControlElementWithState::childrenChanged(change); |
| 414 } | 414 } |
| 415 | 415 |
| 416 void HTMLSelectElement::optionElementChildrenChanged() | 416 void HTMLSelectElement::optionElementChildrenChanged() |
| 417 { | 417 { |
| 418 setRecalcListItems(); | 418 setRecalcListItems(); |
| 419 setNeedsValidityCheck(); | 419 setNeedsValidityCheck(); |
| 420 | 420 |
| 421 if (renderer()) { | 421 if (layoutObject()) { |
| 422 if (AXObjectCache* cache = renderer()->document().existingAXObjectCache(
)) | 422 if (AXObjectCache* cache = layoutObject()->document().existingAXObjectCa
che()) |
| 423 cache->childrenChanged(this); | 423 cache->childrenChanged(this); |
| 424 } | 424 } |
| 425 } | 425 } |
| 426 | 426 |
| 427 void HTMLSelectElement::accessKeyAction(bool sendMouseEvents) | 427 void HTMLSelectElement::accessKeyAction(bool sendMouseEvents) |
| 428 { | 428 { |
| 429 focus(); | 429 focus(); |
| 430 dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEv
ents); | 430 dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEv
ents); |
| 431 } | 431 } |
| 432 | 432 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 int size = listItems.size(); | 534 int size = listItems.size(); |
| 535 for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex +
= direction) { | 535 for (listIndex += direction; listIndex >= 0 && listIndex < size; listIndex +
= direction) { |
| 536 --skip; | 536 --skip; |
| 537 HTMLElement* element = listItems[listIndex]; | 537 HTMLElement* element = listItems[listIndex]; |
| 538 if (!isHTMLOptionElement(*element)) | 538 if (!isHTMLOptionElement(*element)) |
| 539 continue; | 539 continue; |
| 540 if (toHTMLOptionElement(*element).isDisplayNone()) | 540 if (toHTMLOptionElement(*element).isDisplayNone()) |
| 541 continue; | 541 continue; |
| 542 if (element->isDisabledFormControl()) | 542 if (element->isDisabledFormControl()) |
| 543 continue; | 543 continue; |
| 544 if (!usesMenuList() && !element->renderer()) | 544 if (!usesMenuList() && !element->layoutObject()) |
| 545 continue; | 545 continue; |
| 546 lastGoodIndex = listIndex; | 546 lastGoodIndex = listIndex; |
| 547 if (skip <= 0) | 547 if (skip <= 0) |
| 548 break; | 548 break; |
| 549 } | 549 } |
| 550 return lastGoodIndex; | 550 return lastGoodIndex; |
| 551 } | 551 } |
| 552 | 552 |
| 553 int HTMLSelectElement::nextSelectableListIndex(int startIndex) const | 553 int HTMLSelectElement::nextSelectableListIndex(int startIndex) const |
| 554 { | 554 { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 575 { | 575 { |
| 576 return nextValidIndex(-1, SkipForwards, INT_MAX); | 576 return nextValidIndex(-1, SkipForwards, INT_MAX); |
| 577 } | 577 } |
| 578 | 578 |
| 579 // Returns the index of the next valid item one page away from |startIndex| in d
irection |direction|. | 579 // Returns the index of the next valid item one page away from |startIndex| in d
irection |direction|. |
| 580 int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirec
tion direction) const | 580 int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirec
tion direction) const |
| 581 { | 581 { |
| 582 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems()
; | 582 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems()
; |
| 583 // Can't use m_size because renderer forces a minimum size. | 583 // Can't use m_size because renderer forces a minimum size. |
| 584 int pageSize = 0; | 584 int pageSize = 0; |
| 585 if (renderer()->isListBox()) | 585 if (layoutObject()->isListBox()) |
| 586 pageSize = toLayoutListBox(renderer())->size() - 1; // -1 so we still sh
ow context. | 586 pageSize = toLayoutListBox(layoutObject())->size() - 1; // -1 so we stil
l show context. |
| 587 | 587 |
| 588 // One page away, but not outside valid bounds. | 588 // One page away, but not outside valid bounds. |
| 589 // If there is a valid option item one page away, the index is chosen. | 589 // If there is a valid option item one page away, the index is chosen. |
| 590 // If there is no exact one page away valid option, returns startIndex or th
e most far index. | 590 // If there is no exact one page away valid option, returns startIndex or th
e most far index. |
| 591 int edgeIndex = (direction == SkipForwards) ? 0 : (items.size() - 1); | 591 int edgeIndex = (direction == SkipForwards) ? 0 : (items.size() - 1); |
| 592 int skipAmount = pageSize + ((direction == SkipForwards) ? startIndex : (edg
eIndex - startIndex)); | 592 int skipAmount = pageSize + ((direction == SkipForwards) ? startIndex : (edg
eIndex - startIndex)); |
| 593 return nextValidIndex(edgeIndex, direction, skipAmount); | 593 return nextValidIndex(edgeIndex, direction, skipAmount); |
| 594 } | 594 } |
| 595 | 595 |
| 596 void HTMLSelectElement::selectAll() | 596 void HTMLSelectElement::selectAll() |
| 597 { | 597 { |
| 598 ASSERT(!usesMenuList()); | 598 ASSERT(!usesMenuList()); |
| 599 if (!renderer() || !m_multiple) | 599 if (!layoutObject() || !m_multiple) |
| 600 return; | 600 return; |
| 601 | 601 |
| 602 // Save the selection so it can be compared to the new selectAll selection | 602 // Save the selection so it can be compared to the new selectAll selection |
| 603 // when dispatching change events. | 603 // when dispatching change events. |
| 604 saveLastSelection(); | 604 saveLastSelection(); |
| 605 | 605 |
| 606 m_activeSelectionState = true; | 606 m_activeSelectionState = true; |
| 607 setActiveSelectionAnchorIndex(nextSelectableListIndex(-1)); | 607 setActiveSelectionAnchorIndex(nextSelectableListIndex(-1)); |
| 608 setActiveSelectionEndIndex(previousSelectableListIndex(-1)); | 608 setActiveSelectionEndIndex(previousSelectableListIndex(-1)); |
| 609 | 609 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 void HTMLSelectElement::setActiveSelectionEndIndex(int index) | 645 void HTMLSelectElement::setActiveSelectionEndIndex(int index) |
| 646 { | 646 { |
| 647 if (index == m_activeSelectionEndIndex) | 647 if (index == m_activeSelectionEndIndex) |
| 648 return; | 648 return; |
| 649 m_activeSelectionEndIndex = index; | 649 m_activeSelectionEndIndex = index; |
| 650 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
StyleChangeReason::Control)); | 650 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
StyleChangeReason::Control)); |
| 651 } | 651 } |
| 652 | 652 |
| 653 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions, bool s
croll) | 653 void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions, bool s
croll) |
| 654 { | 654 { |
| 655 ASSERT(renderer() && (renderer()->isListBox() || m_multiple)); | 655 ASSERT(layoutObject() && (layoutObject()->isListBox() || m_multiple)); |
| 656 | 656 |
| 657 int start = std::min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex
); | 657 int start = std::min(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex
); |
| 658 int end = std::max(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex); | 658 int end = std::max(m_activeSelectionAnchorIndex, m_activeSelectionEndIndex); |
| 659 | 659 |
| 660 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems()
; | 660 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems()
; |
| 661 for (int i = 0; i < static_cast<int>(items.size()); ++i) { | 661 for (int i = 0; i < static_cast<int>(items.size()); ++i) { |
| 662 HTMLElement* element = items[i]; | 662 HTMLElement* element = items[i]; |
| 663 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi
sabledFormControl() || !toHTMLOptionElement(element)->renderer()) | 663 if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDi
sabledFormControl() || !toHTMLOptionElement(element)->layoutObject()) |
| 664 continue; | 664 continue; |
| 665 | 665 |
| 666 if (i >= start && i <= end) | 666 if (i >= start && i <= end) |
| 667 toHTMLOptionElement(element)->setSelectedState(m_activeSelectionStat
e); | 667 toHTMLOptionElement(element)->setSelectedState(m_activeSelectionStat
e); |
| 668 else if (deselectOtherOptions || i >= static_cast<int>(m_cachedStateForA
ctiveSelection.size())) | 668 else if (deselectOtherOptions || i >= static_cast<int>(m_cachedStateForA
ctiveSelection.size())) |
| 669 toHTMLOptionElement(element)->setSelectedState(false); | 669 toHTMLOptionElement(element)->setSelectedState(false); |
| 670 else | 670 else |
| 671 toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiv
eSelection[i]); | 671 toHTMLOptionElement(element)->setSelectedState(m_cachedStateForActiv
eSelection[i]); |
| 672 } | 672 } |
| 673 | 673 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 return; | 728 return; |
| 729 if (usesMenuList()) | 729 if (usesMenuList()) |
| 730 return; | 730 return; |
| 731 scrollToIndex(activeSelectionEndListIndex()); | 731 scrollToIndex(activeSelectionEndListIndex()); |
| 732 if (AXObjectCache* cache = document().existingAXObjectCache()) | 732 if (AXObjectCache* cache = document().existingAXObjectCache()) |
| 733 cache->selectedChildrenChanged(this); | 733 cache->selectedChildrenChanged(this); |
| 734 } | 734 } |
| 735 | 735 |
| 736 void HTMLSelectElement::setOptionsChangedOnRenderer() | 736 void HTMLSelectElement::setOptionsChangedOnRenderer() |
| 737 { | 737 { |
| 738 if (LayoutObject* renderer = this->renderer()) { | 738 if (LayoutObject* renderer = this->layoutObject()) { |
| 739 if (usesMenuList()) | 739 if (usesMenuList()) |
| 740 toLayoutMenuList(renderer)->setOptionsChanged(true); | 740 toLayoutMenuList(renderer)->setOptionsChanged(true); |
| 741 } | 741 } |
| 742 } | 742 } |
| 743 | 743 |
| 744 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& HTMLSelectElement::list
Items() const | 744 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& HTMLSelectElement::list
Items() const |
| 745 { | 745 { |
| 746 if (m_shouldRecalcListItems) | 746 if (m_shouldRecalcListItems) |
| 747 recalcListItems(); | 747 recalcListItems(); |
| 748 else { | 748 else { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 772 m_activeSelectionAnchorIndex = -1; | 772 m_activeSelectionAnchorIndex = -1; |
| 773 setOptionsChangedOnRenderer(); | 773 setOptionsChangedOnRenderer(); |
| 774 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
StyleChangeReason::ControlValue)); | 774 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
StyleChangeReason::ControlValue)); |
| 775 if (!inDocument()) { | 775 if (!inDocument()) { |
| 776 if (HTMLOptionsCollection* collection = cachedCollection<HTMLOptionsColl
ection>(SelectOptions)) | 776 if (HTMLOptionsCollection* collection = cachedCollection<HTMLOptionsColl
ection>(SelectOptions)) |
| 777 collection->invalidateCache(); | 777 collection->invalidateCache(); |
| 778 } | 778 } |
| 779 if (!inDocument()) | 779 if (!inDocument()) |
| 780 invalidateSelectedItems(); | 780 invalidateSelectedItems(); |
| 781 | 781 |
| 782 if (renderer()) { | 782 if (layoutObject()) { |
| 783 if (AXObjectCache* cache = renderer()->document().existingAXObjectCache(
)) | 783 if (AXObjectCache* cache = layoutObject()->document().existingAXObjectCa
che()) |
| 784 cache->childrenChanged(this); | 784 cache->childrenChanged(this); |
| 785 } | 785 } |
| 786 } | 786 } |
| 787 | 787 |
| 788 void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const | 788 void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const |
| 789 { | 789 { |
| 790 m_listItems.clear(); | 790 m_listItems.clear(); |
| 791 | 791 |
| 792 m_shouldRecalcListItems = false; | 792 m_shouldRecalcListItems = false; |
| 793 | 793 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 | 870 |
| 871 int HTMLSelectElement::suggestedIndex() const | 871 int HTMLSelectElement::suggestedIndex() const |
| 872 { | 872 { |
| 873 return m_suggestedIndex; | 873 return m_suggestedIndex; |
| 874 } | 874 } |
| 875 | 875 |
| 876 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) | 876 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) |
| 877 { | 877 { |
| 878 m_suggestedIndex = suggestedIndex; | 878 m_suggestedIndex = suggestedIndex; |
| 879 | 879 |
| 880 if (LayoutObject* renderer = this->renderer()) { | 880 if (LayoutObject* renderer = this->layoutObject()) { |
| 881 renderer->updateFromElement(); | 881 renderer->updateFromElement(); |
| 882 scrollToIndex(suggestedIndex); | 882 scrollToIndex(suggestedIndex); |
| 883 } | 883 } |
| 884 } | 884 } |
| 885 | 885 |
| 886 void HTMLSelectElement::scrollToIndex(int listIndex) | 886 void HTMLSelectElement::scrollToIndex(int listIndex) |
| 887 { | 887 { |
| 888 if (listIndex < 0) | 888 if (listIndex < 0) |
| 889 return; | 889 return; |
| 890 if (usesMenuList()) | 890 if (usesMenuList()) |
| 891 return; | 891 return; |
| 892 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems()
; | 892 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& items = listItems()
; |
| 893 int listSize = static_cast<int>(items.size()); | 893 int listSize = static_cast<int>(items.size()); |
| 894 if (listIndex >= listSize) | 894 if (listIndex >= listSize) |
| 895 return; | 895 return; |
| 896 document().updateLayoutIgnorePendingStylesheets(); | 896 document().updateLayoutIgnorePendingStylesheets(); |
| 897 if (!renderer() || !renderer()->isListBox()) | 897 if (!layoutObject() || !layoutObject()->isListBox()) |
| 898 return; | 898 return; |
| 899 LayoutRect bounds = items[listIndex]->boundingBox(); | 899 LayoutRect bounds = items[listIndex]->boundingBox(); |
| 900 toLayoutListBox(renderer())->scrollToRect(bounds); | 900 toLayoutListBox(layoutObject())->scrollToRect(bounds); |
| 901 } | 901 } |
| 902 | 902 |
| 903 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b
ool optionIsSelected) | 903 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b
ool optionIsSelected) |
| 904 { | 904 { |
| 905 ASSERT(option->ownerSelectElement() == this); | 905 ASSERT(option->ownerSelectElement() == this); |
| 906 if (optionIsSelected) | 906 if (optionIsSelected) |
| 907 selectOption(option->index()); | 907 selectOption(option->index()); |
| 908 else if (!usesMenuList() || multiple()) | 908 else if (!usesMenuList() || multiple()) |
| 909 selectOption(-1); | 909 selectOption(-1); |
| 910 else | 910 else |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 950 if (m_activeSelectionEndIndex < 0 || shouldDeselect) | 950 if (m_activeSelectionEndIndex < 0 || shouldDeselect) |
| 951 setActiveSelectionEndIndex(listIndex); | 951 setActiveSelectionEndIndex(listIndex); |
| 952 toHTMLOptionElement(*element).setSelectedState(true); | 952 toHTMLOptionElement(*element).setSelectedState(true); |
| 953 } | 953 } |
| 954 } | 954 } |
| 955 | 955 |
| 956 if (shouldDeselect) | 956 if (shouldDeselect) |
| 957 deselectItemsWithoutValidation(element); | 957 deselectItemsWithoutValidation(element); |
| 958 | 958 |
| 959 // For the menu list case, this is what makes the selected element appear. | 959 // For the menu list case, this is what makes the selected element appear. |
| 960 if (LayoutObject* renderer = this->renderer()) | 960 if (LayoutObject* renderer = this->layoutObject()) |
| 961 renderer->updateFromElement(); | 961 renderer->updateFromElement(); |
| 962 | 962 |
| 963 scrollToSelection(); | 963 scrollToSelection(); |
| 964 setNeedsValidityCheck(); | 964 setNeedsValidityCheck(); |
| 965 | 965 |
| 966 if (usesMenuList()) { | 966 if (usesMenuList()) { |
| 967 m_isProcessingUserDrivenChange = flags & UserDriven; | 967 m_isProcessingUserDrivenChange = flags & UserDriven; |
| 968 if (flags & DispatchInputAndChangeEvent) | 968 if (flags & DispatchInputAndChangeEvent) |
| 969 dispatchInputAndChangeEventForMenuList(); | 969 dispatchInputAndChangeEventForMenuList(); |
| 970 if (LayoutObject* renderer = this->renderer()) { | 970 if (LayoutObject* renderer = this->layoutObject()) { |
| 971 if (usesMenuList()) { | 971 if (usesMenuList()) { |
| 972 toLayoutMenuList(renderer)->didSetSelectedIndex(listIndex); | 972 toLayoutMenuList(renderer)->didSetSelectedIndex(listIndex); |
| 973 } else if (renderer->isListBox()) { | 973 } else if (renderer->isListBox()) { |
| 974 if (AXObjectCache* cache = document().existingAXObjectCache()) | 974 if (AXObjectCache* cache = document().existingAXObjectCache()) |
| 975 cache->selectedChildrenChanged(this); | 975 cache->selectedChildrenChanged(this); |
| 976 } | 976 } |
| 977 } | 977 } |
| 978 } | 978 } |
| 979 | 979 |
| 980 notifyFormStateChanged(); | 980 notifyFormStateChanged(); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1187 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
StyleChangeReason::ControlValue)); | 1187 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(
StyleChangeReason::ControlValue)); |
| 1188 setNeedsValidityCheck(); | 1188 setNeedsValidityCheck(); |
| 1189 } | 1189 } |
| 1190 | 1190 |
| 1191 void HTMLSelectElement::handlePopupOpenKeyboardEvent(Event* event) | 1191 void HTMLSelectElement::handlePopupOpenKeyboardEvent(Event* event) |
| 1192 { | 1192 { |
| 1193 focus(); | 1193 focus(); |
| 1194 // Calling focus() may cause us to lose our renderer. Return true so | 1194 // Calling focus() may cause us to lose our renderer. Return true so |
| 1195 // that our caller doesn't process the event further, but don't set | 1195 // that our caller doesn't process the event further, but don't set |
| 1196 // the event as handled. | 1196 // the event as handled. |
| 1197 if (!renderer() || !renderer()->isMenuList() || isDisabledFormControl()) | 1197 if (!layoutObject() || !layoutObject()->isMenuList() || isDisabledFormContro
l()) |
| 1198 return; | 1198 return; |
| 1199 // Save the selection so it can be compared to the new selection | 1199 // Save the selection so it can be compared to the new selection |
| 1200 // when dispatching change events during selectOption, which | 1200 // when dispatching change events during selectOption, which |
| 1201 // gets called from LayoutMenuList::valueChanged, which gets called | 1201 // gets called from LayoutMenuList::valueChanged, which gets called |
| 1202 // after the user makes a selection from the menu. | 1202 // after the user makes a selection from the menu. |
| 1203 saveLastSelection(); | 1203 saveLastSelection(); |
| 1204 if (LayoutMenuList* menuList = toLayoutMenuList(renderer())) | 1204 if (LayoutMenuList* menuList = toLayoutMenuList(layoutObject())) |
| 1205 menuList->showPopup(); | 1205 menuList->showPopup(); |
| 1206 event->setDefaultHandled(); | 1206 event->setDefaultHandled(); |
| 1207 return; | 1207 return; |
| 1208 } | 1208 } |
| 1209 | 1209 |
| 1210 bool HTMLSelectElement::shouldOpenPopupForKeyDownEvent(KeyboardEvent* keyEvent) | 1210 bool HTMLSelectElement::shouldOpenPopupForKeyDownEvent(KeyboardEvent* keyEvent) |
| 1211 { | 1211 { |
| 1212 const String& keyIdentifier = keyEvent->keyIdentifier(); | 1212 const String& keyIdentifier = keyEvent->keyIdentifier(); |
| 1213 LayoutTheme& layoutTheme = LayoutTheme::theme(); | 1213 LayoutTheme& layoutTheme = LayoutTheme::theme(); |
| 1214 | 1214 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1225 LayoutTheme& layoutTheme = LayoutTheme::theme(); | 1225 LayoutTheme& layoutTheme = LayoutTheme::theme(); |
| 1226 int keyCode = event->keyCode(); | 1226 int keyCode = event->keyCode(); |
| 1227 | 1227 |
| 1228 return ((layoutTheme.popsMenuBySpaceKey() && event->keyCode() == ' ') | 1228 return ((layoutTheme.popsMenuBySpaceKey() && event->keyCode() == ' ') |
| 1229 || (layoutTheme.popsMenuByReturnKey() && keyCode == '\r')); | 1229 || (layoutTheme.popsMenuByReturnKey() && keyCode == '\r')); |
| 1230 } | 1230 } |
| 1231 | 1231 |
| 1232 void HTMLSelectElement::menuListDefaultEventHandler(Event* event) | 1232 void HTMLSelectElement::menuListDefaultEventHandler(Event* event) |
| 1233 { | 1233 { |
| 1234 if (event->type() == EventTypeNames::keydown) { | 1234 if (event->type() == EventTypeNames::keydown) { |
| 1235 if (!renderer() || !event->isKeyboardEvent()) | 1235 if (!layoutObject() || !event->isKeyboardEvent()) |
| 1236 return; | 1236 return; |
| 1237 | 1237 |
| 1238 KeyboardEvent* keyEvent = toKeyboardEvent(event); | 1238 KeyboardEvent* keyEvent = toKeyboardEvent(event); |
| 1239 if (shouldOpenPopupForKeyDownEvent(keyEvent)) { | 1239 if (shouldOpenPopupForKeyDownEvent(keyEvent)) { |
| 1240 handlePopupOpenKeyboardEvent(event); | 1240 handlePopupOpenKeyboardEvent(event); |
| 1241 return; | 1241 return; |
| 1242 } | 1242 } |
| 1243 | 1243 |
| 1244 // When using spatial navigation, we want to be able to navigate away | 1244 // When using spatial navigation, we want to be able to navigate away |
| 1245 // from the select element when the user hits any of the arrow keys, | 1245 // from the select element when the user hits any of the arrow keys, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1274 handled = false; | 1274 handled = false; |
| 1275 | 1275 |
| 1276 if (handled && static_cast<size_t>(listIndex) < listItems.size()) | 1276 if (handled && static_cast<size_t>(listIndex) < listItems.size()) |
| 1277 selectOption(listToOptionIndex(listIndex), DeselectOtherOptions | Di
spatchInputAndChangeEvent | UserDriven); | 1277 selectOption(listToOptionIndex(listIndex), DeselectOtherOptions | Di
spatchInputAndChangeEvent | UserDriven); |
| 1278 | 1278 |
| 1279 if (handled) | 1279 if (handled) |
| 1280 event->setDefaultHandled(); | 1280 event->setDefaultHandled(); |
| 1281 } | 1281 } |
| 1282 | 1282 |
| 1283 if (event->type() == EventTypeNames::keypress) { | 1283 if (event->type() == EventTypeNames::keypress) { |
| 1284 if (!renderer() || !event->isKeyboardEvent()) | 1284 if (!layoutObject() || !event->isKeyboardEvent()) |
| 1285 return; | 1285 return; |
| 1286 | 1286 |
| 1287 int keyCode = toKeyboardEvent(event)->keyCode(); | 1287 int keyCode = toKeyboardEvent(event)->keyCode(); |
| 1288 if (keyCode == ' ' && isSpatialNavigationEnabled(document().frame())) { | 1288 if (keyCode == ' ' && isSpatialNavigationEnabled(document().frame())) { |
| 1289 // Use space to toggle arrow key handling for selection change or sp
atial navigation. | 1289 // Use space to toggle arrow key handling for selection change or sp
atial navigation. |
| 1290 m_activeSelectionState = !m_activeSelectionState; | 1290 m_activeSelectionState = !m_activeSelectionState; |
| 1291 event->setDefaultHandled(); | 1291 event->setDefaultHandled(); |
| 1292 return; | 1292 return; |
| 1293 } | 1293 } |
| 1294 | 1294 |
| 1295 KeyboardEvent* keyEvent = toKeyboardEvent(event); | 1295 KeyboardEvent* keyEvent = toKeyboardEvent(event); |
| 1296 if (shouldOpenPopupForKeyPressEvent(keyEvent)) { | 1296 if (shouldOpenPopupForKeyPressEvent(keyEvent)) { |
| 1297 handlePopupOpenKeyboardEvent(event); | 1297 handlePopupOpenKeyboardEvent(event); |
| 1298 return; | 1298 return; |
| 1299 } | 1299 } |
| 1300 | 1300 |
| 1301 if (!LayoutTheme::theme().popsMenuByReturnKey() && keyCode == '\r') { | 1301 if (!LayoutTheme::theme().popsMenuByReturnKey() && keyCode == '\r') { |
| 1302 if (form()) | 1302 if (form()) |
| 1303 form()->submitImplicitly(event, false); | 1303 form()->submitImplicitly(event, false); |
| 1304 dispatchInputAndChangeEventForMenuList(); | 1304 dispatchInputAndChangeEventForMenuList(); |
| 1305 event->setDefaultHandled(); | 1305 event->setDefaultHandled(); |
| 1306 } | 1306 } |
| 1307 } | 1307 } |
| 1308 | 1308 |
| 1309 if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && t
oMouseEvent(event)->button() == LeftButton) { | 1309 if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && t
oMouseEvent(event)->button() == LeftButton) { |
| 1310 focus(); | 1310 focus(); |
| 1311 if (renderer() && renderer()->isMenuList() && !isDisabledFormControl())
{ | 1311 if (layoutObject() && layoutObject()->isMenuList() && !isDisabledFormCon
trol()) { |
| 1312 if (LayoutMenuList* menuList = toLayoutMenuList(renderer())) { | 1312 if (LayoutMenuList* menuList = toLayoutMenuList(layoutObject())) { |
| 1313 if (menuList->popupIsVisible()) | 1313 if (menuList->popupIsVisible()) |
| 1314 menuList->hidePopup(); | 1314 menuList->hidePopup(); |
| 1315 else { | 1315 else { |
| 1316 // Save the selection so it can be compared to the new | 1316 // Save the selection so it can be compared to the new |
| 1317 // selection when we call onChange during selectOption, | 1317 // selection when we call onChange during selectOption, |
| 1318 // which gets called from LayoutMenuList::valueChanged, | 1318 // which gets called from LayoutMenuList::valueChanged, |
| 1319 // which gets called after the user makes a selection from | 1319 // which gets called after the user makes a selection from |
| 1320 // the menu. | 1320 // the menu. |
| 1321 saveLastSelection(); | 1321 saveLastSelection(); |
| 1322 menuList->showPopup(); | 1322 menuList->showPopup(); |
| 1323 } | 1323 } |
| 1324 } | 1324 } |
| 1325 } | 1325 } |
| 1326 event->setDefaultHandled(); | 1326 event->setDefaultHandled(); |
| 1327 } | 1327 } |
| 1328 | 1328 |
| 1329 if (event->type() == EventTypeNames::blur) { | 1329 if (event->type() == EventTypeNames::blur) { |
| 1330 if (LayoutMenuList* menuList = toLayoutMenuList(renderer())) { | 1330 if (LayoutMenuList* menuList = toLayoutMenuList(layoutObject())) { |
| 1331 if (menuList->popupIsVisible()) | 1331 if (menuList->popupIsVisible()) |
| 1332 menuList->hidePopup(); | 1332 menuList->hidePopup(); |
| 1333 } | 1333 } |
| 1334 } | 1334 } |
| 1335 } | 1335 } |
| 1336 | 1336 |
| 1337 void HTMLSelectElement::updateSelectedState(int listIndex, bool multi, bool shif
t) | 1337 void HTMLSelectElement::updateSelectedState(int listIndex, bool multi, bool shif
t) |
| 1338 { | 1338 { |
| 1339 ASSERT(listIndex >= 0); | 1339 ASSERT(listIndex >= 0); |
| 1340 | 1340 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1420 return; | 1420 return; |
| 1421 listBoxOnChange(); | 1421 listBoxOnChange(); |
| 1422 } | 1422 } |
| 1423 | 1423 |
| 1424 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) | 1424 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) |
| 1425 { | 1425 { |
| 1426 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = this->l
istItems(); | 1426 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = this->l
istItems(); |
| 1427 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent())
{ | 1427 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent())
{ |
| 1428 focus(); | 1428 focus(); |
| 1429 // Calling focus() may cause us to lose our renderer or change the rende
r type, in which case do not want to handle the event. | 1429 // Calling focus() may cause us to lose our renderer or change the rende
r type, in which case do not want to handle the event. |
| 1430 if (!renderer() || !renderer()->isListBox()) | 1430 if (!layoutObject() || !layoutObject()->isListBox()) |
| 1431 return; | 1431 return; |
| 1432 | 1432 |
| 1433 // Convert to coords relative to the list box if needed. | 1433 // Convert to coords relative to the list box if needed. |
| 1434 GestureEvent& gestureEvent = toGestureEvent(*event); | 1434 GestureEvent& gestureEvent = toGestureEvent(*event); |
| 1435 int listIndex = listIndexForEventTargetOption(gestureEvent); | 1435 int listIndex = listIndexForEventTargetOption(gestureEvent); |
| 1436 if (listIndex >= 0) { | 1436 if (listIndex >= 0) { |
| 1437 if (!isDisabledFormControl()) { | 1437 if (!isDisabledFormControl()) { |
| 1438 updateSelectedState(listIndex, true, gestureEvent.shiftKey()); | 1438 updateSelectedState(listIndex, true, gestureEvent.shiftKey()); |
| 1439 listBoxOnChange(); | 1439 listBoxOnChange(); |
| 1440 } | 1440 } |
| 1441 event->setDefaultHandled(); | 1441 event->setDefaultHandled(); |
| 1442 } | 1442 } |
| 1443 } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent
() && toMouseEvent(event)->button() == LeftButton) { | 1443 } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent
() && toMouseEvent(event)->button() == LeftButton) { |
| 1444 focus(); | 1444 focus(); |
| 1445 // Calling focus() may cause us to lose our renderer, in which case do n
ot want to handle the event. | 1445 // Calling focus() may cause us to lose our renderer, in which case do n
ot want to handle the event. |
| 1446 if (!renderer() || !renderer()->isListBox() || isDisabledFormControl()) | 1446 if (!layoutObject() || !layoutObject()->isListBox() || isDisabledFormCon
trol()) |
| 1447 return; | 1447 return; |
| 1448 | 1448 |
| 1449 // Convert to coords relative to the list box if needed. | 1449 // Convert to coords relative to the list box if needed. |
| 1450 MouseEvent* mouseEvent = toMouseEvent(event); | 1450 MouseEvent* mouseEvent = toMouseEvent(event); |
| 1451 int listIndex = listIndexForEventTargetOption(*mouseEvent); | 1451 int listIndex = listIndexForEventTargetOption(*mouseEvent); |
| 1452 if (listIndex >= 0) { | 1452 if (listIndex >= 0) { |
| 1453 if (!isDisabledFormControl()) { | 1453 if (!isDisabledFormControl()) { |
| 1454 #if OS(MACOSX) | 1454 #if OS(MACOSX) |
| 1455 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent
->shiftKey()); | 1455 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent
->shiftKey()); |
| 1456 #else | 1456 #else |
| 1457 updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent
->shiftKey()); | 1457 updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent
->shiftKey()); |
| 1458 #endif | 1458 #endif |
| 1459 } | 1459 } |
| 1460 if (LocalFrame* frame = document().frame()) | 1460 if (LocalFrame* frame = document().frame()) |
| 1461 frame->eventHandler().setMouseDownMayStartAutoscroll(); | 1461 frame->eventHandler().setMouseDownMayStartAutoscroll(); |
| 1462 | 1462 |
| 1463 event->setDefaultHandled(); | 1463 event->setDefaultHandled(); |
| 1464 } | 1464 } |
| 1465 } else if (event->type() == EventTypeNames::mousemove && event->isMouseEvent
()) { | 1465 } else if (event->type() == EventTypeNames::mousemove && event->isMouseEvent
()) { |
| 1466 MouseEvent* mouseEvent = toMouseEvent(event); | 1466 MouseEvent* mouseEvent = toMouseEvent(event); |
| 1467 if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown()) | 1467 if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown()) |
| 1468 return; | 1468 return; |
| 1469 | 1469 |
| 1470 if (Page* page = document().page()) | 1470 if (Page* page = document().page()) |
| 1471 page->autoscrollController().startAutoscrollForSelection(renderer())
; | 1471 page->autoscrollController().startAutoscrollForSelection(layoutObjec
t()); |
| 1472 | 1472 |
| 1473 int listIndex = listIndexForEventTargetOption(*mouseEvent); | 1473 int listIndex = listIndexForEventTargetOption(*mouseEvent); |
| 1474 if (listIndex >= 0) { | 1474 if (listIndex >= 0) { |
| 1475 if (!isDisabledFormControl()) { | 1475 if (!isDisabledFormControl()) { |
| 1476 if (m_multiple) { | 1476 if (m_multiple) { |
| 1477 // Only extend selection if there is something selected. | 1477 // Only extend selection if there is something selected. |
| 1478 if (m_activeSelectionAnchorIndex < 0) | 1478 if (m_activeSelectionAnchorIndex < 0) |
| 1479 return; | 1479 return; |
| 1480 | 1480 |
| 1481 setActiveSelectionEndIndex(listIndex); | 1481 setActiveSelectionEndIndex(listIndex); |
| 1482 updateListBoxSelection(false); | 1482 updateListBoxSelection(false); |
| 1483 } else { | 1483 } else { |
| 1484 setActiveSelectionAnchorIndex(listIndex); | 1484 setActiveSelectionAnchorIndex(listIndex); |
| 1485 setActiveSelectionEndIndex(listIndex); | 1485 setActiveSelectionEndIndex(listIndex); |
| 1486 updateListBoxSelection(true); | 1486 updateListBoxSelection(true); |
| 1487 } | 1487 } |
| 1488 } | 1488 } |
| 1489 } | 1489 } |
| 1490 } else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent()
&& toMouseEvent(event)->button() == LeftButton && renderer()) { | 1490 } else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent()
&& toMouseEvent(event)->button() == LeftButton && layoutObject()) { |
| 1491 if (document().page() && document().page()->autoscrollController().autos
crollInProgress(toLayoutBox(renderer()))) | 1491 if (document().page() && document().page()->autoscrollController().autos
crollInProgress(toLayoutBox(layoutObject()))) |
| 1492 document().page()->autoscrollController().stopAutoscroll(); | 1492 document().page()->autoscrollController().stopAutoscroll(); |
| 1493 else | 1493 else |
| 1494 handleMouseRelease(); | 1494 handleMouseRelease(); |
| 1495 } else if (event->type() == EventTypeNames::keydown) { | 1495 } else if (event->type() == EventTypeNames::keydown) { |
| 1496 if (!event->isKeyboardEvent()) | 1496 if (!event->isKeyboardEvent()) |
| 1497 return; | 1497 return; |
| 1498 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); | 1498 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); |
| 1499 | 1499 |
| 1500 bool handled = false; | 1500 bool handled = false; |
| 1501 int endIndex = 0; | 1501 int endIndex = 0; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1589 m_activeSelectionState = !m_activeSelectionState; | 1589 m_activeSelectionState = !m_activeSelectionState; |
| 1590 updateSelectedState(listToOptionIndex(m_activeSelectionEndIndex), tr
ue /*multi*/, false /*shift*/); | 1590 updateSelectedState(listToOptionIndex(m_activeSelectionEndIndex), tr
ue /*multi*/, false /*shift*/); |
| 1591 listBoxOnChange(); | 1591 listBoxOnChange(); |
| 1592 event->setDefaultHandled(); | 1592 event->setDefaultHandled(); |
| 1593 } | 1593 } |
| 1594 } | 1594 } |
| 1595 } | 1595 } |
| 1596 | 1596 |
| 1597 void HTMLSelectElement::defaultEventHandler(Event* event) | 1597 void HTMLSelectElement::defaultEventHandler(Event* event) |
| 1598 { | 1598 { |
| 1599 if (!renderer()) | 1599 if (!layoutObject()) |
| 1600 return; | 1600 return; |
| 1601 | 1601 |
| 1602 if (isDisabledFormControl()) { | 1602 if (isDisabledFormControl()) { |
| 1603 HTMLFormControlElementWithState::defaultEventHandler(event); | 1603 HTMLFormControlElementWithState::defaultEventHandler(event); |
| 1604 return; | 1604 return; |
| 1605 } | 1605 } |
| 1606 | 1606 |
| 1607 if (usesMenuList()) | 1607 if (usesMenuList()) |
| 1608 menuListDefaultEventHandler(event); | 1608 menuListDefaultEventHandler(event); |
| 1609 else | 1609 else |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1768 int focusedIndex = activeSelectionEndListIndex(); | 1768 int focusedIndex = activeSelectionEndListIndex(); |
| 1769 if (focusedIndex < 0) | 1769 if (focusedIndex < 0) |
| 1770 focusedIndex = firstSelectableListIndex(); | 1770 focusedIndex = firstSelectableListIndex(); |
| 1771 if (focusedIndex < 0) | 1771 if (focusedIndex < 0) |
| 1772 return nullptr; | 1772 return nullptr; |
| 1773 HTMLElement* focused = listItems()[focusedIndex]; | 1773 HTMLElement* focused = listItems()[focusedIndex]; |
| 1774 return isHTMLOptionElement(focused) ? toHTMLOptionElement(focused) : nullptr
; | 1774 return isHTMLOptionElement(focused) ? toHTMLOptionElement(focused) : nullptr
; |
| 1775 } | 1775 } |
| 1776 | 1776 |
| 1777 } // namespace | 1777 } // namespace |
| OLD | NEW |