bool DragController::startDrag(Frame* src, const DragState& state, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin) { ASSERT(src); if (!src->view() || !src->contentRenderer()) return false; HitTestResult hitTestResult = src->eventHandler()->hitTestResultAtPoint(dragOrigin, true); if (!state.m_dragSrc->contains(hitTestResult.innerNode())) // The original node being dragged isn't under the drag origin anymore... maybe it was // hidden or moved out from under the cursor. Regardless, we don't want to start a drag on // something that's not actually under the drag origin. return false; KURL linkURL = hitTestResult.absoluteLinkURL(); KURL imageURL = hitTestResult.absoluteImageURL(); IntPoint mouseDraggedPoint = src->view()->windowToContents(dragEvent.position()); m_draggingImageURL = KURL(); m_sourceDragOperation = srcOp; DragImageRef dragImage = 0; IntPoint dragLoc(0, 0); IntPoint dragImageOffset(0, 0); Clipboard* clipboard = state.m_dragClipboard.get(); if (state.m_dragType == DragSourceActionDHTML) dragImage = clipboard->createDragImage(dragImageOffset); if (state.m_dragType == DragSourceActionSelection || !imageURL.isEmpty() || !linkURL.isEmpty()) // Selection, image, and link drags receive a default set of allowed drag operations that // follows from: // http://trac.webkit.org/browser/trunk/WebKit/mac/WebView/WebHTMLView.mm?rev=48526#L3430 m_sourceDragOperation = static_cast<DragOperation>(m_sourceDragOperation | DragOperationGeneric | DragOperationCopy); // We allow DHTML/JS to set the drag image, even if its a link, image or text we're dragging. // This is in the spirit of the IE API, which allows overriding of pasteboard data and DragOp. if (dragImage) { dragLoc = dragLocForDHTMLDrag(mouseDraggedPoint, dragOrigin, dragImageOffset, !linkURL.isEmpty()); m_dragOffset = dragImageOffset; } bool startedDrag = true; // optimism - we almost always manage to start the drag Node* node = state.m_dragSrc.get(); Image* image = getImage(static_cast<Element*>(node)); if (state.m_dragType == DragSourceActionSelection) { if (!clipboard->hasData()) { if (enclosingTextFormControl(src->selection()->start())) clipboard->writePlainText(src->editor()->selectedText()); else { RefPtr<Range> selectionRange = src->selection()->toNormalizedRange(); ASSERT(selectionRange); clipboard->writeRange(selectionRange.get(), src); } } m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard); if (!dragImage) { dragImage = createDragImageForSelection(src); dragLoc = dragLocForSelectionDrag(src); m_dragOffset = IntPoint(dragOrigin.x() - dragLoc.x(), dragOrigin.y() - dragLoc.y()); } doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false); } else if (!imageURL.isEmpty() && node && node->isElementNode() && image && !image->isNull() && (m_dragSourceAction & DragSourceActionImage)) { // We shouldn't be starting a drag for an image that can't provide an extension. // This is an early detection for problems encountered later upon drop. ASSERT(!image->filenameExtension().isEmpty()); Element* element = static_cast<Element*>(node); if (!clipboard->hasData()) { m_draggingImageURL = imageURL; prepareClipboardForImageDrag(src, clipboard, element, linkURL, imageURL, hitTestResult.altDisplayString()); } m_client->willPerformDragSourceAction(DragSourceActionImage, dragOrigin, clipboard); if (!dragImage) { IntRect imageRect = hitTestResult.imageRect(); imageRect.setLocation(m_page->mainFrame()->view()->rootViewToContents(src->view()->contentsToRootView(imageRect.location()))); doImageDrag(element, dragOrigin, hitTestResult.imageRect(), clipboard, src, m_dragOffset); } else // DHTML defined drag image doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false); } else if (!linkURL.isEmpty() && (m_dragSourceAction & DragSourceActionLink)) { if (!clipboard->hasData()) // Simplify whitespace so the title put on the clipboard resembles what the user sees // on the web page. This includes replacing newlines with spaces. clipboard->writeURL(linkURL, hitTestResult.textContent().simplifyWhiteSpace(), src); if (src->selection()->isCaret() && src->selection()->isContentEditable()) { // a user can initiate a drag on a link without having any text // selected. In this case, we should expand the selection to // the enclosing anchor element Position pos = src->selection()->base(); Node* node = enclosingAnchorElement(pos); if (node) src->selection()->setSelection(VisibleSelection::selectionFromContentsOfNode(node)); } m_client->willPerformDragSourceAction(DragSourceActionLink, dragOrigin, clipboard); if (!dragImage) { dragImage = createDragImageForLink(linkURL, hitTestResult.textContent(), src); IntSize size = dragImageSize(dragImage); m_dragOffset = IntPoint(-size.width() / 2, -LinkDragBorderInset); dragLoc = IntPoint(mouseDraggedPoint.x() + m_dragOffset.x(), mouseDraggedPoint.y() + m_dragOffset.y()); } doSystemDrag(dragImage, dragLoc, mouseDraggedPoint, clipboard, src, true); } else if (state.m_dragType == DragSourceActionDHTML) { ASSERT(m_dragSourceAction & DragSourceActionDHTML); m_client->willPerformDragSourceAction(DragSourceActionDHTML, dragOrigin, clipboard); doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false); } else { // draggableNode() determined an image or link node was draggable, but it turns out the // image or link had no URL, so there is nothing to drag. startedDrag = false; } if (dragImage) deleteDragImage(dragImage); return startedDrag; }
bool PopupListBox::handleMouseReleaseEvent(const PlatformMouseEvent& event) { if (m_capturingScrollbar) { m_capturingScrollbar->mouseUp(event); m_capturingScrollbar = 0; return true; } if (!isPointInBounds(event.position())) return true; // Need to check before calling acceptIndex(), because m_popupClient might // be removed in acceptIndex() calling because of event handler. bool isSelectPopup = m_popupClient->menuStyle().menuType() == PopupMenuStyle::SelectPopup; if (acceptIndex(pointToRowIndex(event.position())) && m_focusedElement && isSelectPopup) { m_focusedElement->dispatchMouseEvent(event, EventTypeNames::mouseup); m_focusedElement->dispatchMouseEvent(event, EventTypeNames::click); // Clear m_focusedElement here, because we cannot clear in hidePopup() // which is called before dispatchMouseEvent() is called. m_focusedElement = 0; } return true; }
void Scrollbar::mouseDown(const PlatformMouseEvent& evt) { // Early exit for right click if (evt.pointerProperties().button == WebPointerProperties::Button::Right) return; setPressedPart(theme().hitTest(*this, evt.position())); int pressedPos = orientation() == HorizontalScrollbar ? convertFromRootFrame(evt.position()).x() : convertFromRootFrame(evt.position()).y(); if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && theme().shouldCenterOnThumb(*this, evt)) { setHoveredPart(ThumbPart); setPressedPart(ThumbPart); m_dragOrigin = m_currentPos; int thumbLen = theme().thumbLength(*this); int desiredPos = pressedPos; // Set the pressed position to the middle of the thumb so that when we do // the move, the delta will be from the current pixel position of the thumb // to the new desired position for the thumb. m_pressedPos = theme().trackPosition(*this) + theme().thumbPosition(*this) + thumbLen / 2; moveThumb(desiredPos); return; } if (m_pressedPart == ThumbPart) { m_dragOrigin = m_currentPos; if (m_scrollableArea) m_scrollableArea->mouseCapturedScrollbar(); } m_pressedPos = pressedPos; autoscrollPressedPart(theme().initialAutoscrollTimerDelay()); }
virtual bool mouseEvent(WebPageOverlay& pageOverlay, const PlatformMouseEvent& event) override { switch (event.type()) { case PlatformMouseEvent::Type::MousePressed: { if (!m_client.mouseDown) return false; return m_client.mouseDown(toAPI(&pageOverlay), toAPI(event.position()), toAPI(event.button()), m_client.base.clientInfo); } case PlatformMouseEvent::Type::MouseReleased: { if (!m_client.mouseUp) return false; return m_client.mouseUp(toAPI(&pageOverlay), toAPI(event.position()), toAPI(event.button()), m_client.base.clientInfo); } case PlatformMouseEvent::Type::MouseMoved: { if (event.button() == MouseButton::NoButton) { if (!m_client.mouseMoved) return false; return m_client.mouseMoved(toAPI(&pageOverlay), toAPI(event.position()), m_client.base.clientInfo); } // This is a MouseMove event with a mouse button pressed. Call mouseDragged. if (!m_client.mouseDragged) return false; return m_client.mouseDragged(toAPI(&pageOverlay), toAPI(event.position()), toAPI(event.button()), m_client.base.clientInfo); } default: return false; } }
bool PopupListBox::handleMouseMoveEvent(const PlatformMouseEvent& event) { if (m_capturingScrollbar) { m_capturingScrollbar->mouseMoved(event); return true; } Scrollbar* scrollbar = scrollbarAtPoint(event.position()); if (m_lastScrollbarUnderMouse != scrollbar) { // Send mouse exited to the old scrollbar. if (m_lastScrollbarUnderMouse) m_lastScrollbarUnderMouse->mouseExited(); m_lastScrollbarUnderMouse = scrollbar; } if (scrollbar) { scrollbar->mouseMoved(event); return true; } if (!isPointInBounds(event.position())) return false; selectIndex(pointToRowIndex(event.position())); return true; }
static PlatformMouseEvent constructRelativeMouseEvent(const PlatformMouseEvent& e, FramelessScrollView* parent, FramelessScrollView* child) { IntPoint pos = parent->convertSelfToChild(child, e.position()); // FIXME: This is a horrible hack since PlatformMouseEvent has no setters for x/y. PlatformMouseEvent relativeEvent = e; IntPoint& relativePos = const_cast<IntPoint&>(relativeEvent.position()); relativePos.setX(pos.x()); relativePos.setY(pos.y()); return relativeEvent; }
bool PopupListBox::handleMouseDownEvent(const PlatformMouseEvent& event) { Scrollbar* scrollbar = scrollbarAtPoint(event.position()); if (scrollbar) { m_capturingScrollbar = scrollbar; m_capturingScrollbar->mouseDown(event); return true; } if (!isPointInBounds(event.position())) abandon(); return true; }
bool Scrollbar::mouseDown(const PlatformMouseEvent& evt) { // Early exit for right click if (evt.button() == RightButton) return true; // FIXME: Handled as context menu by Qt right now. Should just avoid even calling this method on a right click though. setPressedPart(theme().hitTest(*this, evt.position())); int pressedPos = (orientation() == HorizontalScrollbar ? convertFromContainingWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y()); if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && theme().shouldCenterOnThumb(*this, evt)) { setHoveredPart(ThumbPart); setPressedPart(ThumbPart); m_dragOrigin = m_currentPos; int thumbLen = theme().thumbLength(*this); int desiredPos = pressedPos; // Set the pressed position to the middle of the thumb so that when we do the move, the delta // will be from the current pixel position of the thumb to the new desired position for the thumb. m_pressedPos = theme().trackPosition(*this) + theme().thumbPosition(*this) + thumbLen / 2; moveThumb(desiredPos); return true; } else if (m_pressedPart == ThumbPart) m_dragOrigin = m_currentPos; m_pressedPos = pressedPos; autoscrollPressedPart(theme().initialAutoscrollTimerDelay()); return true; }
bool Scrollbar::mouseDown(const PlatformMouseEvent& evt) { ScrollbarPart pressedPart = theme().hitTest(*this, evt.position()); auto action = theme().handleMousePressEvent(*this, evt, pressedPart); if (action == ScrollbarButtonPressAction::None) return true; m_scrollableArea.mouseIsDownInScrollbar(this, true); setPressedPart(pressedPart); int pressedPosition = (orientation() == HorizontalScrollbar ? convertFromContainingWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y()); if (action == ScrollbarButtonPressAction::CenterOnThumb) { setHoveredPart(ThumbPart); setPressedPart(ThumbPart); m_dragOrigin = m_currentPos; // Set the pressed position to the middle of the thumb so that when we do the move, the delta // will be from the current pixel position of the thumb to the new desired position for the thumb. m_pressedPos = theme().trackPosition(*this) + theme().thumbPosition(*this) + theme().thumbLength(*this) / 2; moveThumb(pressedPosition); return true; } m_pressedPos = pressedPosition; if (action == ScrollbarButtonPressAction::StartDrag) m_dragOrigin = m_currentPos; if (action == ScrollbarButtonPressAction::Scroll) autoscrollPressedPart(theme().initialAutoscrollTimerDelay()); return true; }
void Scrollbar::mouseDown(const PlatformMouseEvent& evt) { // Early exit for right click if (evt.button() == RightButton) return; setPressedPart(theme()->hitTest(this, evt.position())); int pressedPos = orientation() == HorizontalScrollbar ? convertFromContainingWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y(); if ((m_pressedPart == BackTrackPart || m_pressedPart == ForwardTrackPart) && theme()->shouldCenterOnThumb(this, evt)) { setHoveredPart(ThumbPart); setPressedPart(ThumbPart); m_dragOrigin = m_currentPos; int thumbLen = theme()->thumbLength(this); int desiredPos = pressedPos; // Set the pressed position to the middle of the thumb so that when we do the move, the delta // will be from the current pixel position of the thumb to the new desired position for the thumb. m_pressedPos = theme()->trackPosition(this) + theme()->thumbPosition(this) + thumbLen / 2; moveThumb(desiredPos); return; } else if (m_pressedPart == ThumbPart) m_dragOrigin = m_currentPos; m_pressedPos = pressedPos; autoscrollPressedPart(theme()->initialAutoscrollTimerDelay()); }
void Scrollbar::mouseMoved(const PlatformMouseEvent& evt) { if (m_pressedPart == ThumbPart) { moveThumb(m_orientation == HorizontalScrollbar ? convertFromContainingView(evt.position()).x() : convertFromContainingView(evt.position()).y()); return; } if (m_pressedPart != NoPart) m_pressedPos = orientation() == HorizontalScrollbar ? convertFromContainingView(evt.position()).x() : convertFromContainingView(evt.position()).y(); // FIXME(sky): Cleanup this code now that part is always NoPart. ScrollbarPart part = NoPart; if (part != m_hoveredPart) { if (m_pressedPart != NoPart) { if (part == m_pressedPart) { // The mouse is moving back over the pressed part. We // need to start up the timer action again. startTimerIfNeeded(autoscrollTimerDelay()); invalidatePart(m_pressedPart); } else if (m_hoveredPart == m_pressedPart) { // The mouse is leaving the pressed part. Kill our timer // if needed. stopTimerIfNeeded(); invalidatePart(m_pressedPart); } } setHoveredPart(part); } return; }
ScrollbarPart ScrollbarThemeQStyle::hitTest(ScrollbarThemeClient* scrollbar, const PlatformMouseEvent& evt) { QStyleOptionSlider* opt = styleOptionSlider(scrollbar); const QPoint pos = scrollbar->convertFromContainingWindow(evt.position()); opt->rect.moveTo(QPoint(0, 0)); QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ScrollBar, opt, pos, 0); return scrollbarPart(sc); }
bool ScrollbarTheme::shouldSnapBackToDragOrigin( const ScrollbarThemeClient& scrollbar, const PlatformMouseEvent& evt) { IntPoint mousePosition = scrollbar.convertFromRootFrame(evt.position()); mousePosition.move(scrollbar.x(), scrollbar.y()); return Platform::current()->scrollbarBehavior()->shouldSnapBackToDragOrigin( mousePosition, trackRect(scrollbar), scrollbar.orientation() == HorizontalScrollbar); }
void Scrollbar::mouseMoved(const PlatformMouseEvent& evt) { if (m_pressedPart == ThumbPart) { if (theme().shouldSnapBackToDragOrigin(*this, evt)) { if (m_scrollableArea) { m_scrollableArea->setScrollOffsetSingleAxis( m_orientation, m_dragOrigin + m_scrollableArea->minimumScrollOffset(m_orientation), UserScroll); } } else { moveThumb(m_orientation == HorizontalScrollbar ? convertFromRootFrame(evt.position()).x() : convertFromRootFrame(evt.position()).y(), theme().shouldDragDocumentInsteadOfThumb(*this, evt)); } return; } if (m_pressedPart != NoPart) m_pressedPos = orientation() == HorizontalScrollbar ? convertFromRootFrame(evt.position()).x() : convertFromRootFrame(evt.position()).y(); ScrollbarPart part = theme().hitTest(*this, evt.position()); if (part != m_hoveredPart) { if (m_pressedPart != NoPart) { if (part == m_pressedPart) { // The mouse is moving back over the pressed part. We // need to start up the timer action again. startTimerIfNeeded(theme().autoscrollTimerDelay()); } else if (m_hoveredPart == m_pressedPart) { // The mouse is leaving the pressed part. Kill our timer // if needed. stopTimerIfNeeded(); } } setHoveredPart(part); } return; }
void Scrollbar::mouseMoved(const PlatformMouseEvent& evt) { if (m_pressedPart == ThumbPart) { if (theme()->shouldSnapBackToDragOrigin(this, evt)) { if (m_scrollableArea) m_scrollableArea->scrollToOffsetWithoutAnimation(m_orientation, m_dragOrigin + m_scrollableArea->minimumScrollPosition(m_orientation)); } else { moveThumb(m_orientation == HorizontalScrollbar ? convertFromContainingWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y(), theme()->shouldDragDocumentInsteadOfThumb(this, evt)); } return; } if (m_pressedPart != NoPart) m_pressedPos = orientation() == HorizontalScrollbar ? convertFromContainingWindow(evt.position()).x() : convertFromContainingWindow(evt.position()).y(); ScrollbarPart part = theme()->hitTest(this, evt.position()); if (part != m_hoveredPart) { if (m_pressedPart != NoPart) { if (part == m_pressedPart) { // The mouse is moving back over the pressed part. We // need to start up the timer action again. startTimerIfNeeded(theme()->autoscrollTimerDelay()); theme()->invalidatePart(this, m_pressedPart); } else if (m_hoveredPart == m_pressedPart) { // The mouse is leaving the pressed part. Kill our timer // if needed. stopTimerIfNeeded(); theme()->invalidatePart(this, m_pressedPart); } } setHoveredPart(part); } return; }
Ref<MouseEvent> MouseEvent::create(const AtomicString& eventType, AbstractView* view, const PlatformMouseEvent& event, int detail, PassRefPtr<Node> relatedTarget) { bool isMouseEnterOrLeave = eventType == eventNames().mouseenterEvent || eventType == eventNames().mouseleaveEvent; bool isCancelable = eventType != eventNames().mousemoveEvent && !isMouseEnterOrLeave; bool canBubble = !isMouseEnterOrLeave; return MouseEvent::create(eventType, canBubble, isCancelable, event.timestamp(), view, detail, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(), #if ENABLE(POINTER_LOCK) event.movementDelta().x(), event.movementDelta().y(), #endif event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.button(), relatedTarget, event.force(), event.syntheticClickType()); }
PassRefPtr<MouseEvent> MouseEvent::create(const AtomicString& eventType, PassRefPtr<AbstractView> view, const PlatformMouseEvent& event, int detail, PassRefPtr<Node> relatedTarget) { ASSERT(event.type() == PlatformEvent::MouseMoved || event.button() != NoButton); bool isCancelable = eventType != eventNames().mousemoveEvent; return MouseEvent::create(eventType, true, isCancelable, view, detail, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(), #if ENABLE(POINTER_LOCK) event.movementDelta().x(), event.movementDelta().y(), #endif event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.button(), relatedTarget, 0, false); }
PassRefPtr<MouseEvent> MouseEvent::create(const AtomicString& eventType, PassRefPtr<AbstractView> view, const PlatformMouseEvent& event, int detail, PassRefPtr<Node> relatedTarget) { ASSERT(event.type() == PlatformEvent::MouseMoved || event.button() != NoButton); bool isMouseEnterOrLeave = eventType == EventTypeNames::mouseenter || eventType == EventTypeNames::mouseleave; bool isCancelable = !isMouseEnterOrLeave; bool isBubbling = !isMouseEnterOrLeave; return MouseEvent::create(eventType, isBubbling, isCancelable, view, detail, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(), event.movementDelta().x(), event.movementDelta().y(), event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.button(), relatedTarget, nullptr, false); }
void Scrollbar::mouseUp(const PlatformMouseEvent& mouseEvent) { setPressedPart(NoPart); m_pressedPos = 0; m_draggingDocument = false; stopTimerIfNeeded(); if (m_scrollableArea) { // m_hoveredPart won't be updated until the next mouseMoved or mouseDown, so we have to hit test // to really know if the mouse has exited the scrollbar on a mouseUp. ScrollbarPart part = theme()->hitTest(this, mouseEvent.position()); if (part == NoPart) m_scrollableArea->mouseExitedScrollbar(this); } }
PassRefPtrWillBeRawPtr<MouseEvent> MouseEvent::create(const AtomicString& eventType, PassRefPtrWillBeRawPtr<AbstractView> view, const PlatformMouseEvent& event, int detail, PassRefPtrWillBeRawPtr<Node> relatedTarget) { ASSERT(event.type() == PlatformEvent::MouseMoved || event.button() != NoButton); bool isMouseEnterOrLeave = eventType == EventTypeNames::mouseenter || eventType == EventTypeNames::mouseleave; bool isCancelable = !isMouseEnterOrLeave; bool isBubbling = !isMouseEnterOrLeave; return MouseEvent::create( eventType, isBubbling, isCancelable, view, detail, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(), event.movementDelta().x(), event.movementDelta().y(), event.modifiers(), event.button(), platformModifiersToButtons(event.modifiers()), relatedTarget, event.timestamp(), event.syntheticEventType()); }
bool ScrollbarThemeChromiumWin::shouldSnapBackToDragOrigin(ScrollbarThemeClient* scrollbar, const PlatformMouseEvent& evt) { // Find the rect within which we shouldn't snap, by expanding the track rect // in both dimensions. IntRect rect = trackRect(scrollbar); const bool horz = scrollbar->orientation() == HorizontalScrollbar; const int thickness = scrollbarThickness(scrollbar->controlSize()); rect.inflateX((horz ? kOffEndMultiplier : kOffSideMultiplier) * thickness); rect.inflateY((horz ? kOffSideMultiplier : kOffEndMultiplier) * thickness); // Convert the event to local coordinates. IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.position()); mousePosition.move(scrollbar->x(), scrollbar->y()); // We should snap iff the event is outside our calculated rect. return !rect.contains(mousePosition); }
void Scrollbar::mouseUp(const PlatformMouseEvent& mouseEvent) { bool isCaptured = m_pressedPart == ThumbPart; setPressedPart(NoPart); m_pressedPos = 0; m_draggingDocument = false; stopTimerIfNeeded(); if (m_scrollableArea) { if (isCaptured) m_scrollableArea->mouseReleasedScrollbar(); // m_hoveredPart won't be updated until the next mouseMoved or mouseDown, so // we have to hit test to really know if the mouse has exited the scrollbar // on a mouseUp. ScrollbarPart part = theme().hitTest(*this, mouseEvent.position()); if (part == NoPart) m_scrollableArea->mouseExitedScrollbar(*this); } }
bool Scrollbar::mouseUp(const PlatformMouseEvent& mouseEvent) { setPressedPart(NoPart); m_pressedPos = 0; m_draggingDocument = false; stopTimerIfNeeded(); if (m_scrollableArea) { // m_hoveredPart won't be updated until the next mouseMoved or mouseDown, so we have to hit test // to really know if the mouse has exited the scrollbar on a mouseUp. ScrollbarPart part = theme()->hitTest(this, mouseEvent.position()); if (part == NoPart) m_scrollableArea->mouseExitedScrollbar(this); } if (parent() && parent()->isFrameView()) static_cast<FrameView*>(parent())->frame()->eventHandler()->setMousePressed(false); return true; }
ScrollbarPart ScrollbarThemeComposite::hitTest(ScrollbarThemeClient* scrollbar, const PlatformMouseEvent& evt) { ScrollbarPart result = NoPart; if (!scrollbar->enabled()) return result; IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.position()); mousePosition.move(scrollbar->x(), scrollbar->y()); if (!scrollbar->frameRect().contains(mousePosition)) return NoPart; result = ScrollbarBGPart; IntRect track = trackRect(scrollbar); if (track.contains(mousePosition)) { IntRect beforeThumbRect; IntRect thumbRect; IntRect afterThumbRect; splitTrack(scrollbar, track, beforeThumbRect, thumbRect, afterThumbRect); if (thumbRect.contains(mousePosition)) result = ThumbPart; else if (beforeThumbRect.contains(mousePosition)) result = BackTrackPart; else if (afterThumbRect.contains(mousePosition)) result = ForwardTrackPart; else result = TrackBGPart; } else if (backButtonRect(scrollbar, BackButtonStartPart).contains(mousePosition)) result = BackButtonStartPart; else if (backButtonRect(scrollbar, BackButtonEndPart).contains(mousePosition)) result = BackButtonEndPart; else if (forwardButtonRect(scrollbar, ForwardButtonStartPart).contains(mousePosition)) result = ForwardButtonStartPart; else if (forwardButtonRect(scrollbar, ForwardButtonEndPart).contains(mousePosition)) result = ForwardButtonEndPart; return result; }
void Scrollbar::mouseDown(const PlatformMouseEvent& evt) { // Early exit for right click if (evt.button() == RightButton) return; // FIXME(sky): Do we still need setPressedPart now that we only set it to NoPart? setPressedPart(NoPart); int pressedPos = orientation() == HorizontalScrollbar ? convertFromContainingView(evt.position()).x() : convertFromContainingView(evt.position()).y(); if (m_pressedPart == ThumbPart) m_dragOrigin = m_currentPos; m_pressedPos = pressedPos; autoscrollPressedPart(initialAutoscrollTimerDelay()); }
bool ScrollbarTheme::shouldSnapBackToDragOrigin(ScrollbarThemeClient* scrollbar, const PlatformMouseEvent& evt) { IntPoint mousePosition = scrollbar->convertFromContainingWindow(evt.position()); mousePosition.move(scrollbar->x(), scrollbar->y()); return Platform::current()->scrollbarBehavior()->shouldSnapBackToDragOrigin(mousePosition, trackRect(scrollbar), scrollbar->orientation() == HorizontalScrollbar); }