JSValue* JSMouseEvent::getValueProperty(ExecState* exec, int token) const { switch (token) { case ScreenXAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsNumber(imp->screenX()); } case ScreenYAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsNumber(imp->screenY()); } case ClientXAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsNumber(imp->clientX()); } case ClientYAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsNumber(imp->clientY()); } case CtrlKeyAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsBoolean(imp->ctrlKey()); } case ShiftKeyAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsBoolean(imp->shiftKey()); } case AltKeyAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsBoolean(imp->altKey()); } case MetaKeyAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsBoolean(imp->metaKey()); } case ButtonAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsNumber(imp->button()); } case RelatedTargetAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return toJS(exec, WTF::getPtr(imp->relatedTarget())); } case OffsetXAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsNumber(imp->offsetX()); } case OffsetYAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsNumber(imp->offsetY()); } case XAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsNumber(imp->x()); } case YAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return jsNumber(imp->y()); } case FromElementAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return toJS(exec, WTF::getPtr(imp->fromElement())); } case ToElementAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return toJS(exec, WTF::getPtr(imp->toElement())); } case DataTransferAttrNum: { MouseEvent* imp = static_cast<MouseEvent*>(impl()); return toJS(exec, WTF::getPtr(imp->dataTransfer())); } } return 0; }
static v8::Handle<v8::Value> ctrlKeyAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.MouseEvent.ctrlKey._get"); MouseEvent* imp = V8MouseEvent::toNative(info.Holder()); return v8Boolean(imp->ctrlKey()); }
void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element* element, Event* event, HTMLFormElement* htmlForm) { const Vector<Element*>& listItems = data.listItems(element); if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) { element->focus(); // Convert to coords relative to the list box if needed. MouseEvent* mouseEvent = static_cast<MouseEvent*>(event); IntPoint localOffset = roundedIntPoint(element->renderer()->absoluteToLocal(mouseEvent->absoluteLocation(), false, true)); int listIndex = static_cast<RenderListBox*>(element->renderer())->listIndexAtOffset(localOffset.x(), localOffset.y()); if (listIndex >= 0) { // Save the selection so it can be compared to the new selection when dispatching change events during mouseup, or after autoscroll finishes. saveLastSelection(data, element); data.setActiveSelectionState(true); bool multiSelectKeyPressed = false; #if PLATFORM(MAC) multiSelectKeyPressed = mouseEvent->metaKey(); #else multiSelectKeyPressed = mouseEvent->ctrlKey(); #endif bool shiftSelect = data.multiple() && mouseEvent->shiftKey(); bool multiSelect = data.multiple() && multiSelectKeyPressed && !mouseEvent->shiftKey(); Element* clickedElement = listItems[listIndex]; OptionElement* option = toOptionElement(clickedElement); if (option) { // Keep track of whether an active selection (like during drag selection), should select or deselect if (option->selected() && multiSelectKeyPressed) data.setActiveSelectionState(false); if (!data.activeSelectionState()) option->setSelectedState(false); } // If we're not in any special multiple selection mode, then deselect all other items, excluding the clicked option. // If no option was clicked, then this will deselect all items in the list. if (!shiftSelect && !multiSelect) deselectItems(data, element, clickedElement); // If the anchor hasn't been set, and we're doing a single selection or a shift selection, then initialize the anchor to the first selected index. if (data.activeSelectionAnchorIndex() < 0 && !multiSelect) setActiveSelectionAnchorIndex(data, element, selectedIndex(data, element)); // Set the selection state of the clicked option if (option && !clickedElement->disabled()) option->setSelectedState(true); // If there was no selectedIndex() for the previous initialization, or // If we're doing a single selection, or a multiple selection (using cmd or ctrl), then initialize the anchor index to the listIndex that just got clicked. if (listIndex >= 0 && (data.activeSelectionAnchorIndex() < 0 || !shiftSelect)) setActiveSelectionAnchorIndex(data, element, listIndex); setActiveSelectionEndIndex(data, listIndex); updateListBoxSelection(data, element, !multiSelect); if (Frame* frame = element->document()->frame()) frame->eventHandler()->setMouseDownMayStartAutoscroll(); event->setDefaultHandled(); } } else if (event->type() == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton && element->document()->frame()->eventHandler()->autoscrollRenderer() != element->renderer()) // This makes sure we fire dispatchFormControlChangeEvent for a single click. For drag selection, onChange will fire when the autoscroll timer stops. listBoxOnChange(data, element); else if (event->type() == eventNames().keydownEvent) { if (!event->isKeyboardEvent()) return; String keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier(); int endIndex = 0; if (data.activeSelectionEndIndex() < 0) { // Initialize the end index if (keyIdentifier == "Down") endIndex = nextSelectableListIndex(data, element, lastSelectedListIndex(data, element)); else if (keyIdentifier == "Up") endIndex = previousSelectableListIndex(data, element, optionToListIndex(data, element, selectedIndex(data, element))); } else { // Set the end index based on the current end index if (keyIdentifier == "Down") endIndex = nextSelectableListIndex(data, element, data.activeSelectionEndIndex()); else if (keyIdentifier == "Up") endIndex = previousSelectableListIndex(data, element, data.activeSelectionEndIndex()); } if (keyIdentifier == "Down" || keyIdentifier == "Up") { // Save the selection so it can be compared to the new selection when dispatching change events immediately after making the new selection. saveLastSelection(data, element); ASSERT(endIndex >= 0 && (unsigned) endIndex < listItems.size()); setActiveSelectionEndIndex(data, endIndex); // If the anchor is unitialized, or if we're going to deselect all other options, then set the anchor index equal to the end index. bool deselectOthers = !data.multiple() || !static_cast<KeyboardEvent*>(event)->shiftKey(); if (data.activeSelectionAnchorIndex() < 0 || deselectOthers) { data.setActiveSelectionState(true); if (deselectOthers) deselectItems(data, element); setActiveSelectionAnchorIndex(data, element, data.activeSelectionEndIndex()); } static_cast<RenderListBox*>(element->renderer())->scrollToRevealElementAtListIndex(endIndex); updateListBoxSelection(data, element, deselectOthers); listBoxOnChange(data, element); event->setDefaultHandled(); } } else if (event->type() == eventNames().keypressEvent) { if (!event->isKeyboardEvent()) return; int keyCode = static_cast<KeyboardEvent*>(event)->keyCode(); if (keyCode == '\r') { if (htmlForm) htmlForm->submitClick(event); event->setDefaultHandled(); return; } } }
void HTMLSelectElement::listBoxDefaultEventHandler(Event* evt) { if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) { focus(); MouseEvent* mEvt = static_cast<MouseEvent*>(evt); int listIndex = static_cast<RenderListBox*>(renderer())->listIndexAtOffset(mEvt->offsetX(), mEvt->offsetY()); if (listIndex >= 0) { // Save the selection so it can be compared to the new selection when we call onChange during mouseup, or after autoscroll finishes. saveLastSelection(); m_activeSelectionState = true; bool multiSelectKeyPressed = false; #if PLATFORM(MAC) multiSelectKeyPressed = mEvt->metaKey(); #else multiSelectKeyPressed = mEvt->ctrlKey(); #endif bool shiftSelect = multiple() && mEvt->shiftKey(); bool multiSelect = multiple() && multiSelectKeyPressed && !mEvt->shiftKey(); HTMLElement* clickedElement = listItems()[listIndex]; HTMLOptionElement* option = 0; if (clickedElement->hasLocalName(optionTag)) { option = static_cast<HTMLOptionElement*>(clickedElement); // Keep track of whether an active selection (like during drag selection), should select or deselect if (option->selected() && multiSelectKeyPressed) m_activeSelectionState = false; if (!m_activeSelectionState) option->setSelectedState(false); } // If we're not in any special multiple selection mode, then deselect all other items, excluding the clicked option. // If no option was clicked, then this will deselect all items in the list. if (!shiftSelect && !multiSelect) deselectItems(option); // If the anchor hasn't been set, and we're doing a single selection or a shift selection, then initialize the anchor to the first selected index. if (m_activeSelectionAnchorIndex < 0 && !multiSelect) setActiveSelectionAnchorIndex(selectedIndex()); // Set the selection state of the clicked option if (option && !option->disabled()) option->setSelectedState(true); // If there was no selectedIndex() for the previous initialization, or // If we're doing a single selection, or a multiple selection (using cmd or ctrl), then initialize the anchor index to the listIndex that just got clicked. if (listIndex >= 0 && (m_activeSelectionAnchorIndex < 0 || !shiftSelect)) setActiveSelectionAnchorIndex(listIndex); setActiveSelectionEndIndex(listIndex); updateListBoxSelection(!multiSelect); if (Frame* frame = document()->frame()) frame->eventHandler()->setMouseDownMayStartAutoscroll(); evt->setDefaultHandled(); } } else if (evt->type() == eventNames().mouseupEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton && document()->frame()->eventHandler()->autoscrollRenderer() != renderer()) // This makes sure we fire onChange for a single click. For drag selection, onChange will fire when the autoscroll timer stops. listBoxOnChange(); else if (evt->type() == eventNames().keydownEvent) { if (!evt->isKeyboardEvent()) return; String keyIdentifier = static_cast<KeyboardEvent*>(evt)->keyIdentifier(); int endIndex = 0; if (m_activeSelectionEndIndex < 0) { // Initialize the end index if (keyIdentifier == "Down") endIndex = nextSelectableListIndex(lastSelectedListIndex()); else if (keyIdentifier == "Up") endIndex = previousSelectableListIndex(optionToListIndex(selectedIndex())); } else { // Set the end index based on the current end index if (keyIdentifier == "Down") endIndex = nextSelectableListIndex(m_activeSelectionEndIndex); else if (keyIdentifier == "Up") endIndex = previousSelectableListIndex(m_activeSelectionEndIndex); } if (keyIdentifier == "Down" || keyIdentifier == "Up") { // Save the selection so it can be compared to the new selection when we call onChange immediately after making the new selection. saveLastSelection(); ASSERT(endIndex >= 0 && (unsigned)endIndex < listItems().size()); setActiveSelectionEndIndex(endIndex); // If the anchor is unitialized, or if we're going to deselect all other options, then set the anchor index equal to the end index. bool deselectOthers = !multiple() || !static_cast<KeyboardEvent*>(evt)->shiftKey(); if (m_activeSelectionAnchorIndex < 0 || deselectOthers) { m_activeSelectionState = true; if (deselectOthers) deselectItems(); setActiveSelectionAnchorIndex(m_activeSelectionEndIndex); } static_cast<RenderListBox*>(renderer())->scrollToRevealElementAtListIndex(endIndex); updateListBoxSelection(deselectOthers); listBoxOnChange(); evt->setDefaultHandled(); } } else if (evt->type() == eventNames().keypressEvent) { if (!evt->isKeyboardEvent()) return; int keyCode = static_cast<KeyboardEvent*>(evt)->keyCode(); if (keyCode == '\r') { if (form()) form()->submitClick(evt); evt->setDefaultHandled(); return; } } }