void RenderListBox::scrollToRevealSelection() { HTMLSelectElement* select = toHTMLSelectElement(node()); m_scrollToRevealSelectionAfterLayout = false; int firstIndex = select->activeSelectionStartListIndex(); if (firstIndex >= 0 && !listIndexIsVisible(select->activeSelectionEndListIndex())) scrollToRevealElementAtListIndex(firstIndex); }
static void notifyChildrenSelectionChange(AccessibilityObject* object) { // This static variables are needed to keep track of the old // focused object and its associated list object, as per previous // calls to this function, in order to properly decide whether to // emit some signals or not. static NeverDestroyed<RefPtr<AccessibilityObject>> oldListObject; static NeverDestroyed<RefPtr<AccessibilityObject>> oldFocusedObject; // Only list boxes and menu lists supported so far. if (!object || !(object->isListBox() || object->isMenuList())) return; // Only support HTML select elements so far (ARIA selectors not supported). Node* node = object->node(); if (!node || !isHTMLSelectElement(node)) return; // Emit signal from the listbox's point of view first. g_signal_emit_by_name(object->wrapper(), "selection-changed"); // Find the item where the selection change was triggered from. HTMLSelectElement* select = toHTMLSelectElement(node); if (!select) return; int changedItemIndex = select->activeSelectionStartListIndex(); AccessibilityObject* listObject = getListObject(object); if (!listObject) { oldListObject.get() = 0; return; } const AccessibilityObject::AccessibilityChildrenVector& items = listObject->children(); if (changedItemIndex < 0 || changedItemIndex >= static_cast<int>(items.size())) return; AccessibilityObject* item = items.at(changedItemIndex).get(); // Ensure the current list object is the same than the old one so // further comparisons make sense. Otherwise, just reset // oldFocusedObject so it won't be taken into account. if (oldListObject.get() != listObject) oldFocusedObject.get() = 0; AtkObject* axItem = item ? item->wrapper() : 0; AtkObject* axOldFocusedObject = oldFocusedObject.get() ? oldFocusedObject.get()->wrapper() : 0; // Old focused object just lost focus, so emit the events. if (axOldFocusedObject && axItem != axOldFocusedObject) { g_signal_emit_by_name(axOldFocusedObject, "focus-event", false); atk_object_notify_state_change(axOldFocusedObject, ATK_STATE_FOCUSED, false); } // Emit needed events for the currently (un)selected item. if (axItem) { bool isSelected = item->isSelected(); atk_object_notify_state_change(axItem, ATK_STATE_SELECTED, isSelected); g_signal_emit_by_name(axItem, "focus-event", isSelected); atk_object_notify_state_change(axItem, ATK_STATE_FOCUSED, isSelected); } // Update pointers to the previously involved objects. oldListObject.get() = listObject; oldFocusedObject.get() = item; }