eventhandler.cpp

来自「linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自Web」· C++ 代码 · 共 1,735 行 · 第 1/5 页

CPP
1,735
字号
/* * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */#include "config.h"#include "EventHandler.h"#include "AXObjectCache.h"#include "CachedImage.h"#include "ChromeClient.h"#include "Cursor.h"#include "Document.h"#include "DragController.h"#include "Editor.h"#include "EventNames.h"#include "FloatPoint.h"#include "FloatRect.h"#include "FocusController.h"#include "Frame.h"#include "FrameLoader.h"#include "FrameTree.h"#include "FrameView.h"#include "HitTestRequest.h"#include "HitTestResult.h"#include "HTMLFrameSetElement.h"#include "HTMLFrameElementBase.h"#include "HTMLInputElement.h"#include "HTMLNames.h"#include "Image.h"#include "InspectorController.h"#include "KeyboardEvent.h"#include "MouseEvent.h"#include "MouseEventWithHitTestResults.h"#include "Page.h"#include "PlatformKeyboardEvent.h"#include "PlatformWheelEvent.h"#include "RenderFrameSet.h"#include "RenderTextControlSingleLine.h"#include "RenderWidget.h"#include "RenderView.h"#include "Scrollbar.h"#include "SelectionController.h"#include "Settings.h"#include "TextEvent.h"#include <wtf/StdLibExtras.h>#if ENABLE(SVG)#include "SVGDocument.h"#include "SVGElementInstance.h"#include "SVGNames.h"#include "SVGUseElement.h"#endifnamespace WebCore {using namespace HTMLNames;// The link drag hysteresis is much larger than the others because there// needs to be enough space to cancel the link press without starting a link drag,// and because dragging links is rare.const int LinkDragHysteresis = 40;const int ImageDragHysteresis = 5;const int TextDragHysteresis = 3;const int GeneralDragHysteresis = 3;// Match key code of composition keydown event on windows.// IE sends VK_PROCESSKEY which has value 229;const int CompositionEventKeyCode = 229;#if ENABLE(SVG)using namespace SVGNames;#endif// When the autoscroll or the panScroll is triggered when do the scroll every 0.05s to make it smoothconst double autoscrollInterval = 0.05;static Frame* subframeForTargetNode(Node*);static Frame* subframeForHitTestResult(const MouseEventWithHitTestResults&);static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDirection, ScrollDirection negativeDirection, PlatformWheelEvent& e, Node* node){    if (!delta)        return;            // Find the nearest enclosing box.    RenderBox* enclosingBox = node->renderer()->enclosingBox();    if (e.granularity() == ScrollByPageWheelEvent) {        if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPage, 1))            e.accept();        return;    }     float pixelsToScroll = delta > 0 ? delta : -delta;    if (enclosingBox->scroll(delta < 0 ? negativeDirection : positiveDirection, ScrollByPixel, pixelsToScroll))        e.accept();}EventHandler::EventHandler(Frame* frame)    : m_frame(frame)    , m_mousePressed(false)    , m_capturesDragging(false)    , m_mouseDownMayStartSelect(false)    , m_mouseDownMayStartDrag(false)    , m_mouseDownWasSingleClickInSelection(false)    , m_beganSelectingText(false)    , m_panScrollInProgress(false)    , m_hoverTimer(this, &EventHandler::hoverTimerFired)    , m_autoscrollTimer(this, &EventHandler::autoscrollTimerFired)    , m_autoscrollRenderer(0)    , m_autoscrollInProgress(false)    , m_mouseDownMayStartAutoscroll(false)    , m_mouseDownWasInSubframe(false)#if ENABLE(SVG)    , m_svgPan(false)#endif    , m_resizeLayer(0)    , m_capturingMouseEventsNode(0)    , m_clickCount(0)    , m_mouseDownTimestamp(0)    , m_pendingFrameUnloadEventCount(0)    , m_pendingFrameBeforeUnloadEventCount(0)#if PLATFORM(MAC)    , m_mouseDownView(nil)    , m_sendingEventToSubview(false)    , m_activationEventNumber(0)#endif{}EventHandler::~EventHandler(){}    EventHandler::EventHandlerDragState& EventHandler::dragState(){    DEFINE_STATIC_LOCAL(EventHandlerDragState, state, ());    return state;}    void EventHandler::clear(){    m_hoverTimer.stop();    m_resizeLayer = 0;    m_nodeUnderMouse = 0;    m_lastNodeUnderMouse = 0;#if ENABLE(SVG)    m_instanceUnderMouse = 0;    m_lastInstanceUnderMouse = 0;#endif    m_lastMouseMoveEventSubframe = 0;    m_lastScrollbarUnderMouse = 0;    m_clickCount = 0;    m_clickNode = 0;    m_frameSetBeingResized = 0;    m_dragTarget = 0;    m_currentMousePosition = IntPoint();    m_mousePressNode = 0;    m_mousePressed = false;    m_capturesDragging = false;    m_capturingMouseEventsNode = 0;}void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result){    Node* innerNode = result.targetNode();    VisibleSelection newSelection;    if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {        VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));        if (pos.isNotNull()) {            newSelection = VisibleSelection(pos);            newSelection.expandUsingGranularity(WordGranularity);        }            if (newSelection.isRange()) {            m_frame->setSelectionGranularity(WordGranularity);            m_beganSelectingText = true;            if (result.event().clickCount() == 2 && m_frame->editor()->isSelectTrailingWhitespaceEnabled())                 newSelection.appendTrailingWhitespace();                    }                if (m_frame->shouldChangeSelection(newSelection))            m_frame->selection()->setSelection(newSelection);    }}void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHitTestResults& result){    if (!result.hitTestResult().isLiveLink())        return selectClosestWordFromMouseEvent(result);    Node* innerNode = result.targetNode();    if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {        VisibleSelection newSelection;        Element* URLElement = result.hitTestResult().URLElement();        VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint()));        if (pos.isNotNull() && pos.deepEquivalent().node()->isDescendantOf(URLElement))            newSelection = VisibleSelection::selectionFromContentsOfNode(URLElement);            if (newSelection.isRange()) {            m_frame->setSelectionGranularity(WordGranularity);            m_beganSelectingText = true;        }        if (m_frame->shouldChangeSelection(newSelection))            m_frame->selection()->setSelection(newSelection);    }}bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestResults& event){    if (event.event().button() != LeftButton)        return false;    if (m_frame->selection()->isRange())        // A double-click when range is already selected        // should not change the selection.  So, do not call        // selectClosestWordFromMouseEvent, but do set        // m_beganSelectingText to prevent handleMouseReleaseEvent        // from setting caret selection.        m_beganSelectingText = true;    else        selectClosestWordFromMouseEvent(event);    return true;}bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestResults& event){    if (event.event().button() != LeftButton)        return false;        Node* innerNode = event.targetNode();    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))        return false;    VisibleSelection newSelection;    VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint()));    if (pos.isNotNull()) {        newSelection = VisibleSelection(pos);        newSelection.expandUsingGranularity(ParagraphGranularity);    }    if (newSelection.isRange()) {        m_frame->setSelectionGranularity(ParagraphGranularity);        m_beganSelectingText = true;    }        if (m_frame->shouldChangeSelection(newSelection))        m_frame->selection()->setSelection(newSelection);    return true;}bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestResults& event){    if (event.event().button() != LeftButton)        return false;        Node* innerNode = event.targetNode();    if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))        return false;    // Extend the selection if the Shift key is down, unless the click is in a link.    bool extendSelection = event.event().shiftKey() && !event.isOverLink();    // Don't restart the selection when the mouse is pressed on an    // existing selection so we can allow for text dragging.    IntPoint vPoint = m_frame->view()->windowToContents(event.event().pos());    if (!extendSelection && m_frame->selection()->contains(vPoint)) {        m_mouseDownWasSingleClickInSelection = true;        return false;    }    VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint()));    if (visiblePos.isNull())        visiblePos = VisiblePosition(innerNode, 0, DOWNSTREAM);    Position pos = visiblePos.deepEquivalent();        VisibleSelection newSelection = m_frame->selection()->selection();    if (extendSelection && newSelection.isCaretOrRange()) {        m_frame->selection()->setLastChangeWasHorizontalExtension(false);                // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection         // was created right-to-left        Position start = newSelection.start();        Position end = newSelection.end();        short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), start.node(), start.offset());        if (before <= 0)            newSelection = VisibleSelection(pos, end);        else            newSelection = VisibleSelection(start, pos);        if (m_frame->selectionGranularity() != CharacterGranularity)            newSelection.expandUsingGranularity(m_frame->selectionGranularity());        m_beganSelectingText = true;    } else {        newSelection = VisibleSelection(visiblePos);        m_frame->setSelectionGranularity(CharacterGranularity);    }        if (m_frame->shouldChangeSelection(newSelection))        m_frame->selection()->setSelection(newSelection);    return true;}bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& event){    // Reset drag state.    dragState().m_dragSrc = 0;    bool singleClick = event.event().clickCount() <= 1;    // If we got the event back, that must mean it wasn't prevented,    // so it's allowed to start a drag or selection.    m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode());        // Careful that the drag starting logic stays in sync with eventMayStartDrag()    m_mouseDownMayStartDrag = singleClick;    m_mouseDownWasSingleClickInSelection = false;    if (event.isOverWidget() && passWidgetMouseDownEventToWidget(event))        return true;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?