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

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

Issue 347773002: Implement select listbox using shadow DOM (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: gixed slow select-max-length.html Created 6 years, 6 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 | Annotate | Revision Log
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 21 matching lines...) Expand all
32 #include "bindings/v8/ExceptionState.h" 32 #include "bindings/v8/ExceptionState.h"
33 #include "bindings/v8/ExceptionStatePlaceholder.h" 33 #include "bindings/v8/ExceptionStatePlaceholder.h"
34 #include "core/HTMLNames.h" 34 #include "core/HTMLNames.h"
35 #include "core/accessibility/AXObjectCache.h" 35 #include "core/accessibility/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/NodeTraversal.h" 38 #include "core/dom/NodeTraversal.h"
39 #include "core/events/GestureEvent.h" 39 #include "core/events/GestureEvent.h"
40 #include "core/events/KeyboardEvent.h" 40 #include "core/events/KeyboardEvent.h"
41 #include "core/events/MouseEvent.h" 41 #include "core/events/MouseEvent.h"
42 #include "core/frame/FrameView.h"
42 #include "core/frame/LocalFrame.h" 43 #include "core/frame/LocalFrame.h"
43 #include "core/html/FormDataList.h" 44 #include "core/html/FormDataList.h"
44 #include "core/html/HTMLFormElement.h" 45 #include "core/html/HTMLFormElement.h"
46 #include "core/html/HTMLOptGroupElement.h"
45 #include "core/html/HTMLOptionElement.h" 47 #include "core/html/HTMLOptionElement.h"
46 #include "core/html/forms/FormController.h" 48 #include "core/html/forms/FormController.h"
49 #include "core/page/AutoscrollController.h"
47 #include "core/page/EventHandler.h" 50 #include "core/page/EventHandler.h"
51 #include "core/page/Page.h"
48 #include "core/page/SpatialNavigation.h" 52 #include "core/page/SpatialNavigation.h"
53 #include "core/rendering/HitTestRequest.h"
54 #include "core/rendering/HitTestResult.h"
49 #include "core/rendering/RenderListBox.h" 55 #include "core/rendering/RenderListBox.h"
50 #include "core/rendering/RenderMenuList.h" 56 #include "core/rendering/RenderMenuList.h"
51 #include "core/rendering/RenderTheme.h" 57 #include "core/rendering/RenderTheme.h"
58 #include "core/rendering/RenderView.h"
52 #include "platform/PlatformMouseEvent.h" 59 #include "platform/PlatformMouseEvent.h"
53 #include "platform/text/PlatformLocale.h" 60 #include "platform/text/PlatformLocale.h"
54 61
55 using namespace WTF::Unicode; 62 using namespace WTF::Unicode;
56 63
57 namespace WebCore { 64 namespace WebCore {
58 65
59 using namespace HTMLNames; 66 using namespace HTMLNames;
60 67
61 // Upper limit agreed upon with representatives of Opera and Mozilla. 68 // Upper limit agreed upon with representatives of Opera and Mozilla.
62 static const unsigned maxSelectItems = 10000; 69 static const unsigned maxSelectItems = 10000;
63 70
64 HTMLSelectElement::HTMLSelectElement(Document& document, HTMLFormElement* form) 71 HTMLSelectElement::HTMLSelectElement(Document& document, HTMLFormElement* form)
65 : HTMLFormControlElementWithState(selectTag, document, form) 72 : HTMLFormControlElementWithState(selectTag, document, form)
66 , m_typeAhead(this) 73 , m_typeAhead(this)
67 , m_size(0) 74 , m_size(0)
68 , m_lastOnChangeIndex(-1) 75 , m_lastOnChangeIndex(-1)
69 , m_activeSelectionAnchorIndex(-1) 76 , m_activeSelectionAnchorIndex(-1)
70 , m_activeSelectionEndIndex(-1) 77 , m_activeSelectionEndIndex(-1)
71 , m_isProcessingUserDrivenChange(false) 78 , m_isProcessingUserDrivenChange(false)
72 , m_multiple(false) 79 , m_multiple(false)
73 , m_activeSelectionState(false) 80 , m_activeSelectionState(false)
74 , m_shouldRecalcListItems(false) 81 , m_shouldRecalcListItems(false)
75 , m_suggestedIndex(-1) 82 , m_suggestedIndex(-1)
83 , m_capturing(false)
76 { 84 {
77 ScriptWrappable::init(this); 85 ScriptWrappable::init(this);
78 setHasCustomStyleCallbacks(); 86 setHasCustomStyleCallbacks();
79 } 87 }
80 88
81 PassRefPtrWillBeRawPtr<HTMLSelectElement> HTMLSelectElement::create(Document& do cument) 89 PassRefPtrWillBeRawPtr<HTMLSelectElement> HTMLSelectElement::create(Document& do cument)
82 { 90 {
83 return adoptRefWillBeNoop(new HTMLSelectElement(document, 0)); 91 return adoptRefWillBeNoop(new HTMLSelectElement(document, 0));
84 } 92 }
85 93
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 sizeAttribute->setValue(attrSize); 335 sizeAttribute->setValue(attrSize);
328 } 336 }
329 size = std::max(size, 1); 337 size = std::max(size, 1);
330 338
331 // Ensure that we've determined selectedness of the items at least once prior to changing the size. 339 // Ensure that we've determined selectedness of the items at least once prior to changing the size.
332 if (oldSize != size) 340 if (oldSize != size)
333 updateListItemSelectedStates(); 341 updateListItemSelectedStates();
334 342
335 m_size = size; 343 m_size = size;
336 setNeedsValidityCheck(); 344 setNeedsValidityCheck();
337 if (m_size != oldSize && inActiveDocument()) { 345 if (m_size != oldSize && document().isActive()) {
338 lazyReattachIfAttached(); 346 // ensureShadowDOM needs to be run even when !inDocument().
esprehn 2014/06/23 21:59:56 ensureUserAgentShadowRoot should be run by ::creat
339 setRecalcListItems(); 347 updateView();
348 if (inDocument())
349 setRecalcListItems();
340 } 350 }
341 } else if (name == multipleAttr) 351 } else if (name == multipleAttr)
342 parseMultipleAttribute(value); 352 parseMultipleAttribute(value);
343 else if (name == accesskeyAttr) { 353 else if (name == accesskeyAttr) {
344 // FIXME: ignore for the moment. 354 // FIXME: ignore for the moment.
345 // 355 //
346 } else if (name == disabledAttr) { 356 } else if (name == disabledAttr) {
347 HTMLFormControlElementWithState::parseAttribute(name, value); 357 HTMLFormControlElementWithState::parseAttribute(name, value);
348 if (renderer() && renderer()->isMenuList()) { 358 if (renderer() && renderer()->isMenuList()) {
349 if (RenderMenuList* menuList = toRenderMenuList(renderer())) { 359 if (RenderMenuList* menuList = toRenderMenuList(renderer())) {
350 if (menuList->popupIsVisible()) 360 if (menuList->popupIsVisible())
351 menuList->hidePopup(); 361 menuList->hidePopup();
352 } 362 }
353 } 363 }
354 364
355 } else 365 } else
356 HTMLFormControlElementWithState::parseAttribute(name, value); 366 HTMLFormControlElementWithState::parseAttribute(name, value);
357 } 367 }
358 368
359 bool HTMLSelectElement::shouldShowFocusRingOnMouseFocus() const 369 bool HTMLSelectElement::shouldShowFocusRingOnMouseFocus() const
360 { 370 {
361 return true; 371 return true;
362 } 372 }
363 373
364 bool HTMLSelectElement::canSelectAll() const 374 bool HTMLSelectElement::canSelectAll() const
365 { 375 {
366 return !usesMenuList(); 376 return !usesMenuList();
367 } 377 }
368 378
369 RenderObject* HTMLSelectElement::createRenderer(RenderStyle*) 379 RenderObject* HTMLSelectElement::createRenderer(RenderStyle* style)
370 { 380 {
371 if (usesMenuList()) 381 if (usesMenuList())
372 return new RenderMenuList(this); 382 return new RenderMenuList(this);
373 return new RenderListBox(this); 383 return new RenderListBox(this);
374 } 384 }
375 385
376 PassRefPtrWillBeRawPtr<HTMLCollection> HTMLSelectElement::selectedOptions() 386 PassRefPtrWillBeRawPtr<HTMLCollection> HTMLSelectElement::selectedOptions()
377 { 387 {
378 updateListItemSelectedStates(); 388 updateListItemSelectedStates();
379 return ensureCachedHTMLCollection(SelectedOptions); 389 return ensureCachedHTMLCollection(SelectedOptions);
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 m_lastOnChangeIndex = selected; 706 m_lastOnChangeIndex = selected;
697 m_isProcessingUserDrivenChange = false; 707 m_isProcessingUserDrivenChange = false;
698 RefPtrWillBeRawPtr<HTMLSelectElement> protector(this); 708 RefPtrWillBeRawPtr<HTMLSelectElement> protector(this);
699 dispatchInputEvent(); 709 dispatchInputEvent();
700 dispatchFormControlChangeEvent(); 710 dispatchFormControlChangeEvent();
701 } 711 }
702 } 712 }
703 713
704 void HTMLSelectElement::scrollToSelection() 714 void HTMLSelectElement::scrollToSelection()
705 { 715 {
716 if (!isFinishedParsingChildren())
717 return;
706 if (usesMenuList()) 718 if (usesMenuList())
707 return; 719 return;
708 720 scrollTo(activeSelectionEndListIndex());
709 if (RenderObject* renderer = this->renderer()) 721 if (AXObjectCache* cache = document().existingAXObjectCache())
710 toRenderListBox(renderer)->selectionChanged(); 722 cache->selectedChildrenChanged(this);
711 } 723 }
712 724
713 void HTMLSelectElement::setOptionsChangedOnRenderer() 725 void HTMLSelectElement::setOptionsChangedOnRenderer()
714 { 726 {
715 if (RenderObject* renderer = this->renderer()) { 727 if (RenderObject* renderer = this->renderer()) {
716 if (usesMenuList()) 728 if (usesMenuList())
717 toRenderMenuList(renderer)->setOptionsChanged(true); 729 toRenderMenuList(renderer)->setOptionsChanged(true);
718 else
719 toRenderListBox(renderer)->setOptionsChanged(true);
720 } 730 }
721 } 731 }
722 732
723 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& HTMLSelectElement::lis tItems() const 733 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& HTMLSelectElement::lis tItems() const
724 { 734 {
725 if (m_shouldRecalcListItems) 735 if (m_shouldRecalcListItems)
726 recalcListItems(); 736 recalcListItems();
727 else { 737 else {
728 #if ASSERT_ENABLED 738 #if ASSERT_ENABLED
729 WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > items = m_listItems; 739 WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > items = m_listItems;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 { 861 {
852 return m_suggestedIndex; 862 return m_suggestedIndex;
853 } 863 }
854 864
855 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) 865 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex)
856 { 866 {
857 m_suggestedIndex = suggestedIndex; 867 m_suggestedIndex = suggestedIndex;
858 868
859 if (RenderObject* renderer = this->renderer()) { 869 if (RenderObject* renderer = this->renderer()) {
860 renderer->updateFromElement(); 870 renderer->updateFromElement();
861 if (renderer->isListBox()) 871 scrollTo(suggestedIndex);
862 toRenderListBox(renderer)->scrollToRevealElementAtListIndex(suggeste dIndex);
863 } 872 }
864 } 873 }
865 874
875 void HTMLSelectElement::scrollTo(int listIndex)
876 {
877 if (listIndex < 0)
878 return;
879 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
880 int listSize = static_cast<int>(items.size());
881 if (listIndex >= listSize)
882 return;
883 items[listIndex]->scrollIntoViewIfNeeded(false);
884 }
885
866 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b ool optionIsSelected) 886 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b ool optionIsSelected)
867 { 887 {
868 ASSERT(option->ownerSelectElement() == this); 888 ASSERT(option->ownerSelectElement() == this);
869 if (optionIsSelected) 889 if (optionIsSelected)
870 selectOption(option->index()); 890 selectOption(option->index());
871 else if (!usesMenuList() || multiple()) 891 else if (!usesMenuList() || multiple())
872 selectOption(-1); 892 selectOption(-1);
873 else 893 else
874 selectOption(nextSelectableListIndex(-1)); 894 selectOption(nextSelectableListIndex(-1));
875 } 895 }
876 896
897 void HTMLSelectElement::optionRemoved(HTMLOptionElement* option)
898 {
899 if (m_activeSelectionAnchorIndex < 0 && m_activeSelectionEndIndex < 0)
900 return;
901 int listIndex = optionToListIndex(option->index());
keishi 2014/06/23 20:42:01 fast/forms/select-max-length.html was slow because
902 if (listIndex <= m_activeSelectionAnchorIndex)
903 m_activeSelectionAnchorIndex--;
904 if (listIndex <= m_activeSelectionEndIndex)
905 m_activeSelectionEndIndex--;
906 }
907
877 void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags) 908 void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags)
878 { 909 {
879 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); 910 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions);
880 911
881 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); 912 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
882 int listIndex = optionToListIndex(optionIndex); 913 int listIndex = optionToListIndex(optionIndex);
883 914
884 HTMLElement* element = 0; 915 HTMLElement* element = 0;
885 if (listIndex >= 0) { 916 if (listIndex >= 0) {
886 element = items[listIndex]; 917 element = items[listIndex];
(...skipping 15 matching lines...) Expand all
902 933
903 scrollToSelection(); 934 scrollToSelection();
904 935
905 setNeedsValidityCheck(); 936 setNeedsValidityCheck();
906 937
907 if (usesMenuList()) { 938 if (usesMenuList()) {
908 m_isProcessingUserDrivenChange = flags & UserDriven; 939 m_isProcessingUserDrivenChange = flags & UserDriven;
909 if (flags & DispatchInputAndChangeEvent) 940 if (flags & DispatchInputAndChangeEvent)
910 dispatchInputAndChangeEventForMenuList(); 941 dispatchInputAndChangeEventForMenuList();
911 if (RenderObject* renderer = this->renderer()) { 942 if (RenderObject* renderer = this->renderer()) {
912 if (usesMenuList()) 943 if (usesMenuList()) {
913 toRenderMenuList(renderer)->didSetSelectedIndex(listIndex); 944 toRenderMenuList(renderer)->didSetSelectedIndex(listIndex);
914 else if (renderer->isListBox()) 945 } else if (renderer->isListBox()) {
915 toRenderListBox(renderer)->selectionChanged(); 946 if (AXObjectCache* cache = document().existingAXObjectCache())
947 cache->selectedChildrenChanged(this);
948 }
916 } 949 }
917 } 950 }
918 951
919 notifyFormStateChanged(); 952 notifyFormStateChanged();
920 } 953 }
921 954
922 int HTMLSelectElement::optionToListIndex(int optionIndex) const 955 int HTMLSelectElement::optionToListIndex(int optionIndex) const
923 { 956 {
924 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); 957 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
925 int listSize = static_cast<int>(items.size()); 958 int listSize = static_cast<int>(items.size());
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 startIndex = foundIndex + 1; 1079 startIndex = foundIndex + 1;
1047 } 1080 }
1048 } 1081 }
1049 1082
1050 setOptionsChangedOnRenderer(); 1083 setOptionsChangedOnRenderer();
1051 setNeedsValidityCheck(); 1084 setNeedsValidityCheck();
1052 } 1085 }
1053 1086
1054 void HTMLSelectElement::parseMultipleAttribute(const AtomicString& value) 1087 void HTMLSelectElement::parseMultipleAttribute(const AtomicString& value)
1055 { 1088 {
1056 bool oldUsesMenuList = usesMenuList();
1057 m_multiple = !value.isNull(); 1089 m_multiple = !value.isNull();
1058 setNeedsValidityCheck(); 1090 setNeedsValidityCheck();
1059 if (oldUsesMenuList != usesMenuList()) 1091
1060 lazyReattachIfAttached(); 1092 updateView();
1093 }
1094
1095 void HTMLSelectElement::updateView()
1096 {
1097 if (!usesMenuList())
1098 ensureUserAgentShadowRoot();
1099 else if (userAgentShadowRoot() && document().lifecycle().stateAllowsDetach() )
esprehn 2014/06/23 21:59:56 This is wrong, you should not be manually interact
1100 userAgentShadowRoot()->detach();
1101 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
1102 unsigned optionCount = 0;
1103 for (unsigned i = 0; i < items.size(); ++i) {
1104 HTMLElement* element = items[i];
1105 if (isHTMLOptionElement(*element)) {
1106 toHTMLOptionElement(*element).updateView();
1107 optionCount++;
1108 } else if (isHTMLOptGroupElement(*element)) {
1109 toHTMLOptGroupElement(*element).updateView();
1110 }
1111 if (optionCount >= maxSelectItems)
1112 break;
1113 }
1114 lazyReattachIfAttached();
esprehn 2014/06/23 21:59:56 If you're going to reattach anyway, then there's n
1061 } 1115 }
1062 1116
1063 bool HTMLSelectElement::appendFormData(FormDataList& list, bool) 1117 bool HTMLSelectElement::appendFormData(FormDataList& list, bool)
1064 { 1118 {
1065 const AtomicString& name = this->name(); 1119 const AtomicString& name = this->name();
1066 if (name.isEmpty()) 1120 if (name.isEmpty())
1067 return false; 1121 return false;
1068 1122
1069 bool successful = false; 1123 bool successful = false;
1070 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( ); 1124 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = listItems( );
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
1328 // we're doing a single selection, or a multiple selection (using cmd or 1382 // we're doing a single selection, or a multiple selection (using cmd or
1329 // ctrl), then initialize the anchor index to the listIndex that just got 1383 // ctrl), then initialize the anchor index to the listIndex that just got
1330 // clicked. 1384 // clicked.
1331 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect) 1385 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect)
1332 setActiveSelectionAnchorIndex(listIndex); 1386 setActiveSelectionAnchorIndex(listIndex);
1333 1387
1334 setActiveSelectionEndIndex(listIndex); 1388 setActiveSelectionEndIndex(listIndex);
1335 updateListBoxSelection(!multiSelect); 1389 updateListBoxSelection(!multiSelect);
1336 } 1390 }
1337 1391
1392 int HTMLSelectElement::listIndexForMouseEvent(const MouseEvent& event)
1393 {
1394 Node* targetNode = event.target()->toNode();
1395 if (targetNode != this)
1396 return listIndexForEvent(event);
1397 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | H itTestRequest::Move | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowCont ent);
esprehn 2014/06/23 21:59:56 Why are you using HitTestRequest::ConfusingAndOfte
keishi 2014/07/01 04:53:33 I was able to remove this hit test.
1398 HitTestResult result(event.absoluteLocation());
1399 document().renderView()->hitTest(request, result);
esprehn 2014/06/23 21:59:56 What makes sure the layout/style is updated before
1400 Node* hitNode = result.targetNode();
1401 if (!hitNode)
1402 return -1;
1403 return listIndexForNode(*hitNode);
1404 }
1405
1406 int HTMLSelectElement::listIndexForEvent(const Event& event)
1407 {
1408 Node* targetNode = event.target()->toNode();
1409 if (!targetNode)
1410 return -1;
1411 return listIndexForNode(*targetNode);
1412 }
1413
1414 int HTMLSelectElement::listIndexForNode(const Node& targetNode)
esprehn 2014/06/23 21:59:56 Can you scope this to a more specific type?
keishi 2014/07/01 04:53:33 Done.
1415 {
1416 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = this->list Items();
1417 for (const Node* node = &targetNode; node; node = node->parentOrShadowHostNo de()) {
esprehn 2014/06/23 21:59:56 This walks all the way up to root of the document,
1418 if (node->isElementNode() && (toElement(node)->hasTagName(optionTag) || toElement(node)->hasTagName(optgroupTag))) {
1419 size_t length = items.size();
1420 for (size_t i = 0; i < length; ++i) {
1421 if (items[i] == node) {
1422 return i;
1423 }
1424 }
1425 }
1426 }
1427 return -1;
1428 }
1429
1430 AutoscrollController* HTMLSelectElement::autoscrollController() const
1431 {
1432 if (Page* page = document().page())
1433 return &page->autoscrollController();
1434 return 0;
1435 }
1436
1338 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) 1437 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
1339 { 1438 {
1340 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this-> listItems(); 1439 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this-> listItems();
1341 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent()) { 1440 if (event->type() == EventTypeNames::gesturetap && event->isGestureEvent()) {
1342 focus(); 1441 focus();
1343 // 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. 1442 // 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.
1344 if (!renderer() || !renderer()->isListBox()) 1443 if (!renderer() || !renderer()->isListBox())
1345 return; 1444 return;
1346 1445
1347 // Convert to coords relative to the list box if needed. 1446 // Convert to coords relative to the list box if needed.
1348 GestureEvent& gestureEvent = toGestureEvent(*event); 1447 GestureEvent& gestureEvent = toGestureEvent(*event);
1349 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(gestu reEvent.absoluteLocation(), UseTransforms)); 1448 int listIndex = listIndexForEvent(gestureEvent);
1350 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize (localOffset));
1351 if (listIndex >= 0) { 1449 if (listIndex >= 0) {
1352 if (!isDisabledFormControl()) 1450 if (!isDisabledFormControl())
1353 updateSelectedState(listIndex, true, gestureEvent.shiftKey()); 1451 updateSelectedState(listIndex, true, gestureEvent.shiftKey());
1354 event->setDefaultHandled(); 1452 event->setDefaultHandled();
1355 } 1453 }
1356 } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent () && toMouseEvent(event)->button() == LeftButton) { 1454 } else if (event->type() == EventTypeNames::mousedown && event->isMouseEvent () && toMouseEvent(event)->button() == LeftButton) {
1357 focus(); 1455 focus();
1358 // Calling focus() may cause us to lose our renderer, in which case do n ot want to handle the event. 1456 // Calling focus() may cause us to lose our renderer, in which case do n ot want to handle the event.
1359 if (!renderer() || !renderer()->isListBox() || isDisabledFormControl()) 1457 if (!renderer() || !renderer()->isListBox() || isDisabledFormControl())
1360 return; 1458 return;
1361 1459
1460 if (Page* page = document().page())
1461 page->autoscrollController().startAutoscrollForSelection(renderer()) ;
1462
1463 if (LocalFrame* frame = document().frame()) {
1464 frame->eventHandler().setCapturingMouseEventsNode(this);
1465 m_capturing = true;
1466 }
1467
1362 // Convert to coords relative to the list box if needed. 1468 // Convert to coords relative to the list box if needed.
1363 MouseEvent* mouseEvent = toMouseEvent(event); 1469 MouseEvent* mouseEvent = toMouseEvent(event);
1364 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouse Event->absoluteLocation(), UseTransforms)); 1470 int listIndex = listIndexForMouseEvent(*mouseEvent);
1365 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize (localOffset));
1366 if (listIndex >= 0) { 1471 if (listIndex >= 0) {
1367 if (!isDisabledFormControl()) { 1472 if (!isDisabledFormControl()) {
1368 #if OS(MACOSX) 1473 #if OS(MACOSX)
1369 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent ->shiftKey()); 1474 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent ->shiftKey());
1370 #else 1475 #else
1371 updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent ->shiftKey()); 1476 updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent ->shiftKey());
1372 #endif 1477 #endif
1373 } 1478 }
1374 if (LocalFrame* frame = document().frame()) 1479 if (LocalFrame* frame = document().frame())
1375 frame->eventHandler().setMouseDownMayStartAutoscroll(); 1480 frame->eventHandler().setMouseDownMayStartAutoscroll();
1376 1481
1377 event->setDefaultHandled(); 1482 event->setDefaultHandled();
1378 } 1483 }
1379 } else if (event->type() == EventTypeNames::mousemove && event->isMouseEvent () && !toRenderBox(renderer())->canBeScrolledAndHasScrollableArea()) { 1484 } else if (event->type() == EventTypeNames::mousemove && event->isMouseEvent ()) {
1380 MouseEvent* mouseEvent = toMouseEvent(event); 1485 MouseEvent* mouseEvent = toMouseEvent(event);
1381 if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown()) 1486 if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown())
1382 return; 1487 return;
1383 1488 int listIndex = listIndexForMouseEvent(*mouseEvent);
1384 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouse Event->absoluteLocation(), UseTransforms));
1385 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize (localOffset));
1386 if (listIndex >= 0) { 1489 if (listIndex >= 0) {
1387 if (!isDisabledFormControl()) { 1490 if (!isDisabledFormControl()) {
1388 if (m_multiple) { 1491 if (m_multiple) {
1389 // Only extend selection if there is something selected. 1492 // Only extend selection if there is something selected.
1390 if (m_activeSelectionAnchorIndex < 0) 1493 if (m_activeSelectionAnchorIndex < 0)
1391 return; 1494 return;
1392 1495
1393 setActiveSelectionEndIndex(listIndex); 1496 setActiveSelectionEndIndex(listIndex);
1394 updateListBoxSelection(false); 1497 updateListBoxSelection(false);
1395 } else { 1498 } else {
1396 setActiveSelectionAnchorIndex(listIndex); 1499 setActiveSelectionAnchorIndex(listIndex);
1397 setActiveSelectionEndIndex(listIndex); 1500 setActiveSelectionEndIndex(listIndex);
1398 updateListBoxSelection(true); 1501 updateListBoxSelection(true);
1399 } 1502 }
1400 } 1503 }
1401 } 1504 }
1402 } else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton && renderer() && !toRenderBox(re nderer())->autoscrollInProgress()) { 1505 } else if (event->type() == EventTypeNames::mouseup && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton && renderer()) {
1506 LocalFrame* frame = document().frame();
1507 if (m_capturing && frame) {
1508 frame->eventHandler().setCapturingMouseEventsNode(nullptr);
1509 m_capturing = false;
1510 }
1403 // We didn't start this click/drag on any options. 1511 // We didn't start this click/drag on any options.
1404 if (m_lastOnChangeSelection.isEmpty()) 1512 if (m_lastOnChangeSelection.isEmpty())
1405 return; 1513 return;
1406 listBoxOnChange(); 1514 listBoxOnChange();
1407 } else if (event->type() == EventTypeNames::keydown) { 1515 } else if (event->type() == EventTypeNames::keydown) {
1408 if (!event->isKeyboardEvent()) 1516 if (!event->isKeyboardEvent())
1409 return; 1517 return;
1410 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); 1518 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier();
1411 1519
1412 bool handled = false; 1520 bool handled = false;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1471 m_activeSelectionState = true; 1579 m_activeSelectionState = true;
1472 // If the anchor is unitialized, or if we're going to deselect all 1580 // If the anchor is unitialized, or if we're going to deselect all
1473 // other options, then set the anchor index equal to the end index. 1581 // other options, then set the anchor index equal to the end index.
1474 bool deselectOthers = !m_multiple || (!toKeyboardEvent(event)->shift Key() && selectNewItem); 1582 bool deselectOthers = !m_multiple || (!toKeyboardEvent(event)->shift Key() && selectNewItem);
1475 if (m_activeSelectionAnchorIndex < 0 || deselectOthers) { 1583 if (m_activeSelectionAnchorIndex < 0 || deselectOthers) {
1476 if (deselectOthers) 1584 if (deselectOthers)
1477 deselectItemsWithoutValidation(); 1585 deselectItemsWithoutValidation();
1478 setActiveSelectionAnchorIndex(m_activeSelectionEndIndex); 1586 setActiveSelectionAnchorIndex(m_activeSelectionEndIndex);
1479 } 1587 }
1480 1588
1481 toRenderListBox(renderer())->scrollToRevealElementAtListIndex(endInd ex); 1589 scrollTo(endIndex);
1482 if (selectNewItem) { 1590 if (selectNewItem) {
1483 updateListBoxSelection(deselectOthers); 1591 updateListBoxSelection(deselectOthers);
1484 listBoxOnChange(); 1592 listBoxOnChange();
1485 } else 1593 } else
1486 scrollToSelection(); 1594 scrollToSelection();
1487 1595
1488 event->setDefaultHandled(); 1596 event->setDefaultHandled();
1489 } 1597 }
1490 } else if (event->type() == EventTypeNames::keypress) { 1598 } else if (event->type() == EventTypeNames::keypress) {
1491 if (!event->isKeyboardEvent()) 1599 if (!event->isKeyboardEvent())
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1622 ++options; 1730 ++options;
1623 } 1731 }
1624 1732
1625 return options; 1733 return options;
1626 } 1734 }
1627 1735
1628 void HTMLSelectElement::finishParsingChildren() 1736 void HTMLSelectElement::finishParsingChildren()
1629 { 1737 {
1630 HTMLFormControlElementWithState::finishParsingChildren(); 1738 HTMLFormControlElementWithState::finishParsingChildren();
1631 updateListItemSelectedStates(); 1739 updateListItemSelectedStates();
1740 scrollToSelection();
1632 } 1741 }
1633 1742
1634 bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeR awPtr<HTMLOptionElement> value, ExceptionState& exceptionState) 1743 bool HTMLSelectElement::anonymousIndexedSetter(unsigned index, PassRefPtrWillBeR awPtr<HTMLOptionElement> value, ExceptionState& exceptionState)
1635 { 1744 {
1636 if (!value) { // undefined or null 1745 if (!value) { // undefined or null
1637 remove(index); 1746 remove(index);
1638 return true; 1747 return true;
1639 } 1748 }
1640 setOption(index, value.get(), exceptionState); 1749 setOption(index, value.get(), exceptionState);
1641 return true; 1750 return true;
(...skipping 15 matching lines...) Expand all
1657 } 1766 }
1658 1767
1659 void HTMLSelectElement::trace(Visitor* visitor) 1768 void HTMLSelectElement::trace(Visitor* visitor)
1660 { 1769 {
1661 #if ENABLE(OILPAN) 1770 #if ENABLE(OILPAN)
1662 visitor->trace(m_listItems); 1771 visitor->trace(m_listItems);
1663 #endif 1772 #endif
1664 HTMLFormControlElementWithState::trace(visitor); 1773 HTMLFormControlElementWithState::trace(visitor);
1665 } 1774 }
1666 1775
1776 void HTMLSelectElement::didAddUserAgentShadowRoot(ShadowRoot& root)
1777 {
1778 RefPtrWillBeRawPtr<HTMLContentElement> content = HTMLContentElement::create( document());
1779 content->setAttribute(selectAttr, "option,optgroup");
1780 root.appendChild(content);
1781 }
1782
1667 } // namespace 1783 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698