| 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 #include "HTMLOptionsCollection.h" | 44 #include "HTMLOptionsCollection.h" |
| 45 #include "KeyboardEvent.h" | 45 #include "KeyboardEvent.h" |
| 46 #include "LocalizedStrings.h" | 46 #include "LocalizedStrings.h" |
| 47 #include "MouseEvent.h" | 47 #include "MouseEvent.h" |
| 48 #include "NodeRenderingContext.h" | 48 #include "NodeRenderingContext.h" |
| 49 #include "NodeTraversal.h" | 49 #include "NodeTraversal.h" |
| 50 #include "Page.h" | 50 #include "Page.h" |
| 51 #include "RenderListBox.h" | 51 #include "RenderListBox.h" |
| 52 #include "RenderMenuList.h" | 52 #include "RenderMenuList.h" |
| 53 #include "RenderTheme.h" | 53 #include "RenderTheme.h" |
| 54 #include "StyleResolver.h" |
| 54 #include "ScriptEventListener.h" | 55 #include "ScriptEventListener.h" |
| 55 #include "SpatialNavigation.h" | 56 #include "SpatialNavigation.h" |
| 56 #include <wtf/text/StringBuilder.h> | 57 #include <wtf/text/StringBuilder.h> |
| 57 #include <wtf/unicode/Unicode.h> | 58 #include <wtf/unicode/Unicode.h> |
| 58 | 59 |
| 59 using namespace std; | 60 using namespace std; |
| 60 using namespace WTF::Unicode; | 61 using namespace WTF::Unicode; |
| 61 | 62 |
| 62 namespace WebCore { | 63 namespace WebCore { |
| 63 | 64 |
| (...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 m_lastOnChangeIndex = selected; | 668 m_lastOnChangeIndex = selected; |
| 668 m_isProcessingUserDrivenChange = false; | 669 m_isProcessingUserDrivenChange = false; |
| 669 dispatchFormControlChangeEvent(); | 670 dispatchFormControlChangeEvent(); |
| 670 } | 671 } |
| 671 } | 672 } |
| 672 | 673 |
| 673 void HTMLSelectElement::scrollToSelection() | 674 void HTMLSelectElement::scrollToSelection() |
| 674 { | 675 { |
| 675 if (usesMenuList()) | 676 if (usesMenuList()) |
| 676 return; | 677 return; |
| 677 | 678 int listIndex = activeSelectionEndListIndex(); |
| 678 if (RenderObject* renderer = this->renderer()) | 679 const Vector<HTMLElement*>& items = listItems(); |
| 679 toRenderListBox(renderer)->selectionChanged(); | 680 int listSize = static_cast<int>(items.size()); |
| 681 if (listIndex < 0 || listIndex >= listSize) |
| 682 return; |
| 683 Element* option = listItems()[listIndex]; |
| 684 option->scrollIntoViewIfNeeded(false); |
| 680 } | 685 } |
| 681 | 686 |
| 682 void HTMLSelectElement::setOptionsChangedOnRenderer() | 687 void HTMLSelectElement::setOptionsChangedOnRenderer() |
| 683 { | 688 { |
| 684 if (RenderObject* renderer = this->renderer()) { | 689 if (RenderObject* renderer = this->renderer()) { |
| 685 if (usesMenuList()) | 690 if (usesMenuList()) |
| 686 toRenderMenuList(renderer)->setOptionsChanged(true); | 691 toRenderMenuList(renderer)->setOptionsChanged(true); |
| 687 else | 692 // else |
| 688 toRenderListBox(renderer)->setOptionsChanged(true); | 693 // scrollToSelection(); |
| 689 } | 694 } |
| 690 } | 695 } |
| 691 | 696 |
| 692 const Vector<HTMLElement*>& HTMLSelectElement::listItems() const | 697 const Vector<HTMLElement*>& HTMLSelectElement::listItems() const |
| 693 { | 698 { |
| 694 if (m_shouldRecalcListItems) | 699 if (m_shouldRecalcListItems) |
| 695 recalcListItems(); | 700 recalcListItems(); |
| 696 else { | 701 else { |
| 697 #if !ASSERT_DISABLED | 702 #if !ASSERT_DISABLED |
| 698 Vector<HTMLElement*> items = m_listItems; | 703 Vector<HTMLElement*> items = m_listItems; |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 | 857 |
| 853 scrollToSelection(); | 858 scrollToSelection(); |
| 854 | 859 |
| 855 if (usesMenuList()) { | 860 if (usesMenuList()) { |
| 856 m_isProcessingUserDrivenChange = flags & UserDriven; | 861 m_isProcessingUserDrivenChange = flags & UserDriven; |
| 857 if (flags & DispatchChangeEvent) | 862 if (flags & DispatchChangeEvent) |
| 858 dispatchChangeEventForMenuList(); | 863 dispatchChangeEventForMenuList(); |
| 859 if (RenderObject* renderer = this->renderer()) { | 864 if (RenderObject* renderer = this->renderer()) { |
| 860 if (usesMenuList()) | 865 if (usesMenuList()) |
| 861 toRenderMenuList(renderer)->didSetSelectedIndex(listIndex); | 866 toRenderMenuList(renderer)->didSetSelectedIndex(listIndex); |
| 862 else if (renderer->isListBox()) | |
| 863 toRenderListBox(renderer)->selectionChanged(); | |
| 864 } | 867 } |
| 865 } | 868 } |
| 866 | 869 |
| 867 setNeedsValidityCheck(); | 870 setNeedsValidityCheck(); |
| 868 notifyFormStateChanged(); | 871 notifyFormStateChanged(); |
| 869 } | 872 } |
| 870 | 873 |
| 871 int HTMLSelectElement::optionToListIndex(int optionIndex) const | 874 int HTMLSelectElement::optionToListIndex(int optionIndex) const |
| 872 { | 875 { |
| 873 const Vector<HTMLElement*>& items = listItems(); | 876 const Vector<HTMLElement*>& items = listItems(); |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1277 // we're doing a single selection, or a multiple selection (using cmd or | 1280 // we're doing a single selection, or a multiple selection (using cmd or |
| 1278 // ctrl), then initialize the anchor index to the listIndex that just got | 1281 // ctrl), then initialize the anchor index to the listIndex that just got |
| 1279 // clicked. | 1282 // clicked. |
| 1280 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect) | 1283 if (m_activeSelectionAnchorIndex < 0 || !shiftSelect) |
| 1281 setActiveSelectionAnchorIndex(listIndex); | 1284 setActiveSelectionAnchorIndex(listIndex); |
| 1282 | 1285 |
| 1283 setActiveSelectionEndIndex(listIndex); | 1286 setActiveSelectionEndIndex(listIndex); |
| 1284 updateListBoxSelection(!multiSelect); | 1287 updateListBoxSelection(!multiSelect); |
| 1285 } | 1288 } |
| 1286 | 1289 |
| 1290 int HTMLSelectElement::listIndexForEvent(Event* event) |
| 1291 { |
| 1292 const Vector<HTMLElement*>& items = this->listItems(); |
| 1293 for (Node* node = event->target()->toNode(); node; node = node->parentOrShad
owHostNode()) { |
| 1294 if (node->isElementNode() && (toElement(node)->hasTagName(optionTag) ||
toElement(node)->hasTagName(optgroupTag))) { |
| 1295 size_t length = items.size(); |
| 1296 for (size_t i = 0; i < length; ++i) { |
| 1297 if (items[i] == node) { |
| 1298 return i; |
| 1299 } |
| 1300 } |
| 1301 } |
| 1302 } |
| 1303 return -1; |
| 1304 } |
| 1305 |
| 1287 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) | 1306 void HTMLSelectElement::listBoxDefaultEventHandler(Event* event) |
| 1288 { | 1307 { |
| 1289 const Vector<HTMLElement*>& listItems = this->listItems(); | 1308 const Vector<HTMLElement*>& listItems = this->listItems(); |
| 1290 | 1309 |
| 1291 if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() &&
static_cast<MouseEvent*>(event)->button() == LeftButton) { | 1310 if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() &&
static_cast<MouseEvent*>(event)->button() == LeftButton) { |
| 1292 focus(); | 1311 focus(); |
| 1293 // Calling focus() may cause us to lose our renderer, in which case do n
ot want to handle the event. | 1312 // Calling focus() may cause us to lose our renderer, in which case do n
ot want to handle the event. |
| 1294 if (!renderer()) | 1313 if (!renderer()) |
| 1295 return; | 1314 return; |
| 1296 | 1315 |
| 1297 // Convert to coords relative to the list box if needed. | |
| 1298 MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); | 1316 MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); |
| 1299 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouse
Event->absoluteLocation(), UseTransforms)); | 1317 int listIndex = listIndexForEvent(event); |
| 1300 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize
(localOffset)); | |
| 1301 if (listIndex >= 0) { | 1318 if (listIndex >= 0) { |
| 1302 if (!isDisabledFormControl()) { | 1319 if (!isDisabledFormControl()) { |
| 1303 #if OS(DARWIN) | 1320 #if OS(DARWIN) |
| 1304 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent
->shiftKey()); | 1321 updateSelectedState(listIndex, mouseEvent->metaKey(), mouseEvent
->shiftKey()); |
| 1305 #else | 1322 #else |
| 1306 updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent
->shiftKey()); | 1323 updateSelectedState(listIndex, mouseEvent->ctrlKey(), mouseEvent
->shiftKey()); |
| 1307 #endif | 1324 #endif |
| 1308 } | 1325 } |
| 1309 if (Frame* frame = document()->frame()) | 1326 if (Frame* frame = document()->frame()) |
| 1310 frame->eventHandler()->setMouseDownMayStartAutoscroll(); | 1327 frame->eventHandler()->setMouseDownMayStartAutoscroll(); |
| 1311 | 1328 |
| 1312 event->setDefaultHandled(); | 1329 event->setDefaultHandled(); |
| 1313 } | 1330 } |
| 1314 } else if (event->type() == eventNames().mousemoveEvent && event->isMouseEve
nt() && !toRenderBox(renderer())->canBeScrolledAndHasScrollableArea()) { | 1331 } else if (event->type() == eventNames().mousemoveEvent && event->isMouseEve
nt()) { |
| 1315 MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); | 1332 MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); |
| 1316 if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown()) | 1333 if (mouseEvent->button() != LeftButton || !mouseEvent->buttonDown()) |
| 1317 return; | 1334 return; |
| 1318 | 1335 |
| 1319 IntPoint localOffset = roundedIntPoint(renderer()->absoluteToLocal(mouse
Event->absoluteLocation(), UseTransforms)); | 1336 int listIndex = listIndexForEvent(event); |
| 1320 int listIndex = toRenderListBox(renderer())->listIndexAtOffset(toIntSize
(localOffset)); | |
| 1321 if (listIndex >= 0) { | 1337 if (listIndex >= 0) { |
| 1322 if (!isDisabledFormControl()) { | 1338 if (!isDisabledFormControl()) { |
| 1323 if (m_multiple) { | 1339 if (m_multiple) { |
| 1324 // Only extend selection if there is something selected. | 1340 // Only extend selection if there is something selected. |
| 1325 if (m_activeSelectionAnchorIndex < 0) | 1341 if (m_activeSelectionAnchorIndex < 0) |
| 1326 return; | 1342 return; |
| 1327 | 1343 |
| 1328 setActiveSelectionEndIndex(listIndex); | 1344 setActiveSelectionEndIndex(listIndex); |
| 1329 updateListBoxSelection(false); | 1345 updateListBoxSelection(false); |
| 1330 } else { | 1346 } else { |
| 1331 setActiveSelectionAnchorIndex(listIndex); | 1347 setActiveSelectionAnchorIndex(listIndex); |
| 1332 setActiveSelectionEndIndex(listIndex); | 1348 setActiveSelectionEndIndex(listIndex); |
| 1333 updateListBoxSelection(true); | 1349 updateListBoxSelection(true); |
| 1334 } | 1350 } |
| 1335 } | 1351 } |
| 1336 event->setDefaultHandled(); | 1352 event->setDefaultHandled(); |
| 1337 } | 1353 } |
| 1338 } else if (event->type() == eventNames().mouseupEvent && event->isMouseEvent
() && static_cast<MouseEvent*>(event)->button() == LeftButton && document()->fra
me()->eventHandler()->autoscrollRenderer() != renderer()) { | 1354 } else if (event->type() == eventNames().mouseupEvent && event->isMouseEvent
() && static_cast<MouseEvent*>(event)->button() == LeftButton) |
| 1339 // This makes sure we fire dispatchFormControlChangeEvent for a single | |
| 1340 // click. For drag selection, onChange will fire when the autoscroll | |
| 1341 // timer stops. | |
| 1342 listBoxOnChange(); | 1355 listBoxOnChange(); |
| 1343 } else if (event->type() == eventNames().keydownEvent) { | 1356 else if (event->type() == eventNames().keydownEvent) { |
| 1344 if (!event->isKeyboardEvent()) | 1357 if (!event->isKeyboardEvent()) |
| 1345 return; | 1358 return; |
| 1346 const String& keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIde
ntifier(); | 1359 const String& keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIde
ntifier(); |
| 1347 | 1360 |
| 1348 bool handled = false; | 1361 bool handled = false; |
| 1349 int endIndex = 0; | 1362 int endIndex = 0; |
| 1350 if (m_activeSelectionEndIndex < 0) { | 1363 if (m_activeSelectionEndIndex < 0) { |
| 1351 // Initialize the end index | 1364 // Initialize the end index |
| 1352 if (keyIdentifier == "Down" || keyIdentifier == "PageDown") { | 1365 if (keyIdentifier == "Down" || keyIdentifier == "PageDown") { |
| 1353 int startIndex = lastSelectedListIndex(); | 1366 int startIndex = lastSelectedListIndex(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 m_activeSelectionState = true; | 1420 m_activeSelectionState = true; |
| 1408 // If the anchor is unitialized, or if we're going to deselect all | 1421 // If the anchor is unitialized, or if we're going to deselect all |
| 1409 // other options, then set the anchor index equal to the end index. | 1422 // other options, then set the anchor index equal to the end index. |
| 1410 bool deselectOthers = !m_multiple || (!static_cast<KeyboardEvent*>(e
vent)->shiftKey() && selectNewItem); | 1423 bool deselectOthers = !m_multiple || (!static_cast<KeyboardEvent*>(e
vent)->shiftKey() && selectNewItem); |
| 1411 if (m_activeSelectionAnchorIndex < 0 || deselectOthers) { | 1424 if (m_activeSelectionAnchorIndex < 0 || deselectOthers) { |
| 1412 if (deselectOthers) | 1425 if (deselectOthers) |
| 1413 deselectItemsWithoutValidation(); | 1426 deselectItemsWithoutValidation(); |
| 1414 setActiveSelectionAnchorIndex(m_activeSelectionEndIndex); | 1427 setActiveSelectionAnchorIndex(m_activeSelectionEndIndex); |
| 1415 } | 1428 } |
| 1416 | 1429 |
| 1417 toRenderListBox(renderer())->scrollToRevealElementAtListIndex(endInd
ex); | 1430 listItems[endIndex]->scrollIntoViewIfNeeded(false); |
| 1418 if (selectNewItem) { | 1431 if (selectNewItem) { |
| 1419 updateListBoxSelection(deselectOthers); | 1432 updateListBoxSelection(deselectOthers); |
| 1420 listBoxOnChange(); | 1433 listBoxOnChange(); |
| 1421 } else | 1434 } else |
| 1422 scrollToSelection(); | 1435 scrollToSelection(); |
| 1423 | 1436 |
| 1424 event->setDefaultHandled(); | 1437 event->setDefaultHandled(); |
| 1425 } | 1438 } |
| 1426 } else if (event->type() == eventNames().keypressEvent) { | 1439 } else if (event->type() == eventNames().keypressEvent) { |
| 1427 if (!event->isKeyboardEvent()) | 1440 if (!event->isKeyboardEvent()) |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1554 | 1567 |
| 1555 const Vector<HTMLElement*>& items = listItems(); | 1568 const Vector<HTMLElement*>& items = listItems(); |
| 1556 for (unsigned i = 0; i < items.size(); ++i) { | 1569 for (unsigned i = 0; i < items.size(); ++i) { |
| 1557 if (items[i]->hasTagName(optionTag)) | 1570 if (items[i]->hasTagName(optionTag)) |
| 1558 ++options; | 1571 ++options; |
| 1559 } | 1572 } |
| 1560 | 1573 |
| 1561 return options; | 1574 return options; |
| 1562 } | 1575 } |
| 1563 | 1576 |
| 1577 void HTMLSelectElement::dispatchFormControlChangeEvent() |
| 1578 { |
| 1579 if (renderer() && renderer()->isListBox()) { |
| 1580 AXObjectCache* cache = document()->existingAXObjectCache(); |
| 1581 if (cache) |
| 1582 cache->selectedChildrenChanged(renderer()); |
| 1583 } |
| 1584 HTMLFormControlElement::dispatchChangeEvent(); |
| 1585 } |
| 1586 |
| 1564 } // namespace | 1587 } // namespace |
| OLD | NEW |