Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 2001 Peter Kelly (pmk (at) post.com)
      3  * Copyright (C) 2001 Tobias Anton (anton (at) stud.fbi.fh-darmstadt.de)
      4  * Copyright (C) 2006 Samuel Weinig (sam.weinig (at) gmail.com)
      5  * Copyright (C) 2003, 2005, 2006, 2008 Apple Inc. All rights reserved.
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Library General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Library General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Library General Public License
     18  * along with this library; see the file COPYING.LIB.  If not, write to
     19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     20  * Boston, MA 02110-1301, USA.
     21  */
     22 
     23 #include "config.h"
     24 #include "MouseRelatedEvent.h"
     25 
     26 #include "DOMWindow.h"
     27 #include "Document.h"
     28 #include "Frame.h"
     29 #include "FrameView.h"
     30 #include "RenderLayer.h"
     31 #include "RenderObject.h"
     32 
     33 namespace WebCore {
     34 
     35 MouseRelatedEvent::MouseRelatedEvent()
     36     : m_screenX(0)
     37     , m_screenY(0)
     38     , m_clientX(0)
     39     , m_clientY(0)
     40     , m_pageX(0)
     41     , m_pageY(0)
     42     , m_layerX(0)
     43     , m_layerY(0)
     44     , m_offsetX(0)
     45     , m_offsetY(0)
     46     , m_isSimulated(false)
     47     , m_hasCachedRelativePosition(false)
     48 {
     49 }
     50 
     51 static int contentsX(AbstractView* abstractView)
     52 {
     53     if (!abstractView)
     54         return 0;
     55     Frame* frame = abstractView->frame();
     56     if (!frame)
     57         return 0;
     58     FrameView* frameView = frame->view();
     59     if (!frameView)
     60         return 0;
     61     return frameView->scrollX() / frame->pageZoomFactor();
     62 }
     63 
     64 static int contentsY(AbstractView* abstractView)
     65 {
     66     if (!abstractView)
     67         return 0;
     68     Frame* frame = abstractView->frame();
     69     if (!frame)
     70         return 0;
     71     FrameView* frameView = frame->view();
     72     if (!frameView)
     73         return 0;
     74     return frameView->scrollY() / frame->pageZoomFactor();
     75 }
     76 
     77 MouseRelatedEvent::MouseRelatedEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtr<AbstractView> abstractView,
     78                                      int detail, int screenX, int screenY, int windowX, int windowY,
     79                                      bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, bool isSimulated)
     80     : UIEventWithKeyState(eventType, canBubble, cancelable, abstractView, detail, ctrlKey, altKey, shiftKey, metaKey)
     81     , m_screenX(screenX)
     82     , m_screenY(screenY)
     83     , m_clientX(0)
     84     , m_clientY(0)
     85     , m_pageX(0)
     86     , m_pageY(0)
     87     , m_isSimulated(isSimulated)
     88 {
     89     IntPoint adjustedPageLocation;
     90     IntPoint scrollPosition;
     91 
     92     Frame* frame = view() ? view()->frame() : 0;
     93     if (frame && !isSimulated) {
     94         if (FrameView* frameView = frame->view()) {
     95             scrollPosition = frameView->scrollPosition();
     96             adjustedPageLocation = frameView->windowToContents(IntPoint(windowX, windowY));
     97             float pageZoom = frame->pageZoomFactor();
     98             if (pageZoom != 1.0f) {
     99                 // Adjust our pageX and pageY to account for the page zoom.
    100                 adjustedPageLocation.setX(lroundf(adjustedPageLocation.x() / pageZoom));
    101                 adjustedPageLocation.setY(lroundf(adjustedPageLocation.y() / pageZoom));
    102                 scrollPosition.setX(scrollPosition.x() / pageZoom);
    103                 scrollPosition.setY(scrollPosition.y() / pageZoom);
    104             }
    105         }
    106     }
    107 
    108     IntPoint clientLocation(adjustedPageLocation - scrollPosition);
    109     m_clientX = clientLocation.x();
    110     m_clientY = clientLocation.y();
    111     m_pageX = adjustedPageLocation.x();
    112     m_pageY = adjustedPageLocation.y();
    113 
    114     initCoordinates();
    115 }
    116 
    117 void MouseRelatedEvent::initCoordinates()
    118 {
    119     // Set up initial values for coordinates.
    120     // Correct values are computed lazily, see computeRelativePosition.
    121     m_layerX = m_pageX;
    122     m_layerY = m_pageY;
    123     m_offsetX = m_pageX;
    124     m_offsetY = m_pageY;
    125 
    126     computePageLocation();
    127     m_hasCachedRelativePosition = false;
    128 }
    129 
    130 void MouseRelatedEvent::initCoordinates(int clientX, int clientY)
    131 {
    132     // Set up initial values for coordinates.
    133     // Correct values are computed lazily, see computeRelativePosition.
    134     m_clientX = clientX;
    135     m_clientY = clientY;
    136     m_pageX = clientX + contentsX(view());
    137     m_pageY = clientY + contentsY(view());
    138     m_layerX = m_pageX;
    139     m_layerY = m_pageY;
    140     m_offsetX = m_pageX;
    141     m_offsetY = m_pageY;
    142 
    143     computePageLocation();
    144     m_hasCachedRelativePosition = false;
    145 }
    146 
    147 static float pageZoomFactor(const UIEvent* event)
    148 {
    149     DOMWindow* window = event->view();
    150     if (!window)
    151         return 1;
    152     Frame* frame = window->frame();
    153     if (!frame)
    154         return 1;
    155     return frame->pageZoomFactor();
    156 }
    157 
    158 void MouseRelatedEvent::computePageLocation()
    159 {
    160     float zoomFactor = pageZoomFactor(this);
    161     setAbsoluteLocation(roundedIntPoint(FloatPoint(pageX() * zoomFactor, pageY() * zoomFactor)));
    162 }
    163 
    164 void MouseRelatedEvent::receivedTarget()
    165 {
    166     m_hasCachedRelativePosition = false;
    167 }
    168 
    169 void MouseRelatedEvent::computeRelativePosition()
    170 {
    171     Node* targetNode = target() ? target()->toNode() : 0;
    172     if (!targetNode)
    173         return;
    174 
    175     // Compute coordinates that are based on the target.
    176     m_layerX = m_pageX;
    177     m_layerY = m_pageY;
    178     m_offsetX = m_pageX;
    179     m_offsetY = m_pageY;
    180 
    181     // Must have an updated render tree for this math to work correctly.
    182     targetNode->document()->updateStyleIfNeeded();
    183 
    184     // Adjust offsetX/Y to be relative to the target's position.
    185     if (!isSimulated()) {
    186         if (RenderObject* r = targetNode->renderer()) {
    187             FloatPoint localPos = r->absoluteToLocal(absoluteLocation(), false, true);
    188             float zoomFactor = pageZoomFactor(this);
    189             m_offsetX = lroundf(localPos.x() / zoomFactor);
    190             m_offsetY = lroundf(localPos.y() / zoomFactor);
    191         }
    192     }
    193 
    194     // Adjust layerX/Y to be relative to the layer.
    195     // FIXME: We're pretty sure this is the wrong definition of "layer."
    196     // Our RenderLayer is a more modern concept, and layerX/Y is some
    197     // other notion about groups of elements (left over from the Netscape 4 days?);
    198     // we should test and fix this.
    199     Node* n = targetNode;
    200     while (n && !n->renderer())
    201         n = n->parentNode();
    202 
    203     RenderLayer* layer;
    204     if (n && (layer = n->renderer()->enclosingLayer())) {
    205         layer->updateLayerPosition();
    206         for (; layer; layer = layer->parent()) {
    207             m_layerX -= layer->x();
    208             m_layerY -= layer->y();
    209         }
    210     }
    211 
    212     m_hasCachedRelativePosition = true;
    213 }
    214 
    215 int MouseRelatedEvent::layerX()
    216 {
    217     if (!m_hasCachedRelativePosition)
    218         computeRelativePosition();
    219     return m_layerX;
    220 }
    221 
    222 int MouseRelatedEvent::layerY()
    223 {
    224     if (!m_hasCachedRelativePosition)
    225         computeRelativePosition();
    226     return m_layerY;
    227 }
    228 
    229 int MouseRelatedEvent::offsetX()
    230 {
    231     if (!m_hasCachedRelativePosition)
    232         computeRelativePosition();
    233     return m_offsetX;
    234 }
    235 
    236 int MouseRelatedEvent::offsetY()
    237 {
    238     if (!m_hasCachedRelativePosition)
    239         computeRelativePosition();
    240     return m_offsetY;
    241 }
    242 
    243 int MouseRelatedEvent::pageX() const
    244 {
    245     return m_pageX;
    246 }
    247 
    248 int MouseRelatedEvent::pageY() const
    249 {
    250     return m_pageY;
    251 }
    252 
    253 int MouseRelatedEvent::x() const
    254 {
    255     // FIXME: This is not correct.
    256     // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>.
    257     return m_clientX;
    258 }
    259 
    260 int MouseRelatedEvent::y() const
    261 {
    262     // FIXME: This is not correct.
    263     // See Microsoft documentation and <http://www.quirksmode.org/dom/w3c_events.html>.
    264     return m_clientY;
    265 }
    266 
    267 } // namespace WebCore
    268