bool nsSliderFrame::ShouldScrollToClickForEvent(WidgetGUIEvent* aEvent) { if (!ShouldScrollForEvent(aEvent)) { return false; } if (aEvent->message == NS_TOUCH_START) { return GetScrollToClick(); } if (aEvent->message != NS_MOUSE_BUTTON_DOWN) { return false; } #ifdef XP_MACOSX // On Mac, clicking the scrollbar thumb should never scroll to click. if (IsEventOverThumb(aEvent)) { return false; } #endif WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent(); if (mouseEvent->button == WidgetMouseEvent::eLeftButton) { #ifdef XP_MACOSX bool invertPref = mouseEvent->IsAlt(); #else bool invertPref = mouseEvent->IsShift(); #endif return GetScrollToClick() != invertPref; } return true; }
bool nsSliderFrame::ShouldScrollToClickForEvent(WidgetGUIEvent* aEvent) { if (!ShouldScrollForEvent(aEvent)) { return false; } if (aEvent->mMessage != eMouseDown && aEvent->mMessage != eTouchStart) { return false; } #if defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK) // On Mac and Linux, clicking the scrollbar thumb should never scroll to click. if (IsEventOverThumb(aEvent)) { return false; } #endif if (aEvent->mMessage == eTouchStart) { return GetScrollToClick(); } WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent(); if (mouseEvent->button == WidgetMouseEvent::eLeftButton) { #ifdef XP_MACOSX bool invertPref = mouseEvent->IsAlt(); #else bool invertPref = mouseEvent->IsShift(); #endif return GetScrollToClick() != invertPref; } #ifdef MOZ_WIDGET_GTK if (mouseEvent->button == WidgetMouseEvent::eRightButton) { return !GetScrollToClick(); } #endif return true; }
nsresult HTMLLabelElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent(); if (mHandlingEvent || (!(mouseEvent && mouseEvent->IsLeftClickEvent()) && aVisitor.mEvent->mMessage != eMouseDown) || aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault || !aVisitor.mPresContext || // Don't handle the event if it's already been handled by another label aVisitor.mEvent->mFlags.mMultipleActionsPrevented) { return NS_OK; } nsCOMPtr<nsIContent> target = do_QueryInterface(aVisitor.mEvent->target); if (InInteractiveHTMLContent(target, this)) { return NS_OK; } // Strong ref because event dispatch is going to happen. RefPtr<Element> content = GetLabeledElement(); if (content) { mHandlingEvent = true; switch (aVisitor.mEvent->mMessage) { case eMouseDown: if (mouseEvent->button == WidgetMouseEvent::eLeftButton) { // We reset the mouse-down point on every event because there is // no guarantee we will reach the eMouseClick code below. LayoutDeviceIntPoint* curPoint = new LayoutDeviceIntPoint(mouseEvent->refPoint); SetProperty(nsGkAtoms::labelMouseDownPtProperty, static_cast<void*>(curPoint), nsINode::DeleteProperty<LayoutDeviceIntPoint>); } break; case eMouseClick: if (mouseEvent->IsLeftClickEvent()) { LayoutDeviceIntPoint* mouseDownPoint = static_cast<LayoutDeviceIntPoint*>( GetProperty(nsGkAtoms::labelMouseDownPtProperty)); bool dragSelect = false; if (mouseDownPoint) { LayoutDeviceIntPoint dragDistance = *mouseDownPoint; DeleteProperty(nsGkAtoms::labelMouseDownPtProperty); dragDistance -= mouseEvent->refPoint; const int CLICK_DISTANCE = 2; dragSelect = dragDistance.x > CLICK_DISTANCE || dragDistance.x < -CLICK_DISTANCE || dragDistance.y > CLICK_DISTANCE || dragDistance.y < -CLICK_DISTANCE; } // Don't click the for-content if we did drag-select text or if we // have a kbd modifier (which adjusts a selection). if (dragSelect || mouseEvent->IsShift() || mouseEvent->IsControl() || mouseEvent->IsAlt() || mouseEvent->IsMeta()) { break; } // Only set focus on the first click of multiple clicks to prevent // to prevent immediate de-focus. if (mouseEvent->clickCount <= 1) { nsIFocusManager* fm = nsFocusManager::GetFocusManager(); if (fm) { // Use FLAG_BYMOVEFOCUS here so that the label is scrolled to. // Also, within HTMLInputElement::PostHandleEvent, inputs will // be selected only when focused via a key or when the navigation // flag is used and we want to select the text on label clicks as // well. // If the label has been clicked by the user, we also want to // pass FLAG_BYMOUSE so that we get correct focus ring behavior, // but we don't want to pass FLAG_BYMOUSE if this click event was // caused by the user pressing an accesskey. nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(content); bool byMouse = (mouseEvent->inputSource != nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD); bool byTouch = (mouseEvent->inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH); fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOVEFOCUS | (byMouse ? nsIFocusManager::FLAG_BYMOUSE : 0) | (byTouch ? nsIFocusManager::FLAG_BYTOUCH : 0)); } } // Dispatch a new click event to |content| // (For compatibility with IE, we do only left click. If // we wanted to interpret the HTML spec very narrowly, we // would do nothing. If we wanted to do something // sensible, we might send more events through like // this.) See bug 7554, bug 49897, and bug 96813. nsEventStatus status = aVisitor.mEventStatus; // Ok to use aVisitor.mEvent as parameter because DispatchClickEvent // will actually create a new event. EventFlags eventFlags; eventFlags.mMultipleActionsPrevented = true; DispatchClickEvent(aVisitor.mPresContext, mouseEvent, content, false, &eventFlags, &status); // Do we care about the status this returned? I don't think we do... // Don't run another <label> off of this click mouseEvent->mFlags.mMultipleActionsPrevented = true; } break; default: break; } mHandlingEvent = false; } return NS_OK; }