Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / events / MouseEvent.cpp
1 /*
2  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
3  * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
4  * Copyright (C) 2006 Samuel Weinig (sam.weinig@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 "core/events/MouseEvent.h"
25
26 #include "core/clipboard/DataTransfer.h"
27 #include "core/dom/Element.h"
28 #include "core/events/EventDispatcher.h"
29 #include "platform/PlatformMouseEvent.h"
30
31 namespace blink {
32
33 MouseEventInit::MouseEventInit()
34     : screenX(0)
35     , screenY(0)
36     , clientX(0)
37     , clientY(0)
38     , ctrlKey(false)
39     , altKey(false)
40     , shiftKey(false)
41     , metaKey(false)
42     , button(0)
43     , relatedTarget(nullptr)
44 {
45 }
46
47 PassRefPtrWillBeRawPtr<MouseEvent> MouseEvent::create(const AtomicString& type, const MouseEventInit& initializer)
48 {
49     return adoptRefWillBeNoop(new MouseEvent(type, initializer));
50 }
51
52 PassRefPtrWillBeRawPtr<MouseEvent> MouseEvent::create(const AtomicString& eventType, PassRefPtrWillBeRawPtr<AbstractView> view, const PlatformMouseEvent& event, int detail, PassRefPtrWillBeRawPtr<Node> relatedTarget)
53 {
54     ASSERT(event.type() == PlatformEvent::MouseMoved || event.button() != NoButton);
55
56     bool isMouseEnterOrLeave = eventType == EventTypeNames::mouseenter || eventType == EventTypeNames::mouseleave;
57     bool isCancelable = !isMouseEnterOrLeave;
58     bool isBubbling = !isMouseEnterOrLeave;
59
60     return MouseEvent::create(
61         eventType, isBubbling, isCancelable, view,
62         detail, event.globalPosition().x(), event.globalPosition().y(), event.position().x(), event.position().y(),
63         event.movementDelta().x(), event.movementDelta().y(),
64         event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(), event.button(),
65         relatedTarget, nullptr, false);
66 }
67
68 PassRefPtrWillBeRawPtr<MouseEvent> MouseEvent::create(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<AbstractView> view,
69     int detail, int screenX, int screenY, int pageX, int pageY,
70     int movementX, int movementY,
71     bool ctrlKey, bool altKey, bool shiftKey, bool metaKey, unsigned short button,
72     PassRefPtrWillBeRawPtr<EventTarget> relatedTarget, PassRefPtrWillBeRawPtr<DataTransfer> dataTransfer, bool isSimulated)
73 {
74     return adoptRefWillBeNoop(new MouseEvent(type, canBubble, cancelable, view,
75         detail, screenX, screenY, pageX, pageY,
76         movementX, movementY,
77         ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget, dataTransfer, isSimulated));
78 }
79
80 MouseEvent::MouseEvent()
81     : m_button(0)
82     , m_buttonDown(false)
83 {
84     ScriptWrappable::init(this);
85 }
86
87 MouseEvent::MouseEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<AbstractView> view,
88     int detail, int screenX, int screenY, int pageX, int pageY,
89     int movementX, int movementY,
90     bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
91     unsigned short button, PassRefPtrWillBeRawPtr<EventTarget> relatedTarget,
92     PassRefPtrWillBeRawPtr<DataTransfer> dataTransfer, bool isSimulated)
93     : MouseRelatedEvent(eventType, canBubble, cancelable, view, detail, IntPoint(screenX, screenY),
94                         IntPoint(pageX, pageY),
95                         IntPoint(movementX, movementY),
96                         ctrlKey, altKey, shiftKey, metaKey, isSimulated)
97     , m_button(button == (unsigned short)-1 ? 0 : button)
98     , m_buttonDown(button != (unsigned short)-1)
99     , m_relatedTarget(relatedTarget)
100     , m_dataTransfer(dataTransfer)
101 {
102     ScriptWrappable::init(this);
103 }
104
105 MouseEvent::MouseEvent(const AtomicString& eventType, const MouseEventInit& initializer)
106     : MouseRelatedEvent(eventType, initializer.bubbles, initializer.cancelable, initializer.view, initializer.detail, IntPoint(initializer.screenX, initializer.screenY),
107         IntPoint(0 /* pageX */, 0 /* pageY */),
108         IntPoint(0 /* movementX */, 0 /* movementY */),
109         initializer.ctrlKey, initializer.altKey, initializer.shiftKey, initializer.metaKey, false /* isSimulated */)
110     , m_button(initializer.button == (unsigned short)-1 ? 0 : initializer.button)
111     , m_buttonDown(initializer.button != (unsigned short)-1)
112     , m_relatedTarget(initializer.relatedTarget)
113     , m_dataTransfer(nullptr)
114 {
115     ScriptWrappable::init(this);
116     initCoordinates(IntPoint(initializer.clientX, initializer.clientY));
117 }
118
119 MouseEvent::~MouseEvent()
120 {
121 }
122
123 void MouseEvent::initMouseEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<AbstractView> view,
124                                 int detail, int screenX, int screenY, int clientX, int clientY,
125                                 bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
126                                 unsigned short button, PassRefPtrWillBeRawPtr<EventTarget> relatedTarget)
127 {
128     if (dispatched())
129         return;
130
131     initUIEvent(type, canBubble, cancelable, view, detail);
132
133     m_screenLocation = IntPoint(screenX, screenY);
134     m_ctrlKey = ctrlKey;
135     m_altKey = altKey;
136     m_shiftKey = shiftKey;
137     m_metaKey = metaKey;
138     m_button = button == (unsigned short)-1 ? 0 : button;
139     m_buttonDown = button != (unsigned short)-1;
140     m_relatedTarget = relatedTarget;
141
142     initCoordinates(IntPoint(clientX, clientY));
143
144     // FIXME: m_isSimulated is not set to false here.
145     // FIXME: m_dataTransfer is not set to nullptr here.
146 }
147
148 const AtomicString& MouseEvent::interfaceName() const
149 {
150     return EventNames::MouseEvent;
151 }
152
153 bool MouseEvent::isMouseEvent() const
154 {
155     return true;
156 }
157
158 bool MouseEvent::isDragEvent() const
159 {
160     const AtomicString& t = type();
161     return t == EventTypeNames::dragenter || t == EventTypeNames::dragover || t == EventTypeNames::dragleave || t == EventTypeNames::drop
162                || t == EventTypeNames::dragstart|| t == EventTypeNames::drag || t == EventTypeNames::dragend;
163 }
164
165 int MouseEvent::which() const
166 {
167     // For the DOM, the return values for left, middle and right mouse buttons are 0, 1, 2, respectively.
168     // For the Netscape "which" property, the return values for left, middle and right mouse buttons are 1, 2, 3, respectively.
169     // So we must add 1.
170     if (!m_buttonDown)
171         return 0;
172     return m_button + 1;
173 }
174
175 Node* MouseEvent::toElement() const
176 {
177     // MSIE extension - "the object toward which the user is moving the mouse pointer"
178     if (type() == EventTypeNames::mouseout || type() == EventTypeNames::mouseleave)
179         return relatedTarget() ? relatedTarget()->toNode() : 0;
180
181     return target() ? target()->toNode() : 0;
182 }
183
184 Node* MouseEvent::fromElement() const
185 {
186     // MSIE extension - "object from which activation or the mouse pointer is exiting during the event" (huh?)
187     if (type() != EventTypeNames::mouseout && type() != EventTypeNames::mouseleave)
188         return relatedTarget() ? relatedTarget()->toNode() : 0;
189
190     return target() ? target()->toNode() : 0;
191 }
192
193 void MouseEvent::trace(Visitor* visitor)
194 {
195     visitor->trace(m_relatedTarget);
196     visitor->trace(m_dataTransfer);
197     MouseRelatedEvent::trace(visitor);
198 }
199
200 PassRefPtrWillBeRawPtr<SimulatedMouseEvent> SimulatedMouseEvent::create(const AtomicString& eventType, PassRefPtrWillBeRawPtr<AbstractView> view, PassRefPtrWillBeRawPtr<Event> underlyingEvent)
201 {
202     return adoptRefWillBeNoop(new SimulatedMouseEvent(eventType, view, underlyingEvent));
203 }
204
205 SimulatedMouseEvent::~SimulatedMouseEvent()
206 {
207 }
208
209 SimulatedMouseEvent::SimulatedMouseEvent(const AtomicString& eventType, PassRefPtrWillBeRawPtr<AbstractView> view, PassRefPtrWillBeRawPtr<Event> underlyingEvent)
210     : MouseEvent(eventType, true, true, view, 0, 0, 0, 0, 0,
211                  0, 0,
212                  false, false, false, false, 0, nullptr, nullptr, true)
213 {
214     if (UIEventWithKeyState* keyStateEvent = findEventWithKeyState(underlyingEvent.get())) {
215         m_ctrlKey = keyStateEvent->ctrlKey();
216         m_altKey = keyStateEvent->altKey();
217         m_shiftKey = keyStateEvent->shiftKey();
218         m_metaKey = keyStateEvent->metaKey();
219     }
220     setUnderlyingEvent(underlyingEvent);
221
222     if (this->underlyingEvent() && this->underlyingEvent()->isMouseEvent()) {
223         MouseEvent* mouseEvent = toMouseEvent(this->underlyingEvent());
224         m_screenLocation = mouseEvent->screenLocation();
225         initCoordinates(mouseEvent->clientLocation());
226     }
227 }
228
229 void SimulatedMouseEvent::trace(Visitor* visitor)
230 {
231     MouseEvent::trace(visitor);
232 }
233
234 PassRefPtrWillBeRawPtr<MouseEventDispatchMediator> MouseEventDispatchMediator::create(PassRefPtrWillBeRawPtr<MouseEvent> mouseEvent, MouseEventType mouseEventType)
235 {
236     return adoptRefWillBeNoop(new MouseEventDispatchMediator(mouseEvent, mouseEventType));
237 }
238
239 MouseEventDispatchMediator::MouseEventDispatchMediator(PassRefPtrWillBeRawPtr<MouseEvent> mouseEvent, MouseEventType mouseEventType)
240     : EventDispatchMediator(mouseEvent), m_mouseEventType(mouseEventType)
241 {
242 }
243
244 MouseEvent* MouseEventDispatchMediator::event() const
245 {
246     return toMouseEvent(EventDispatchMediator::event());
247 }
248
249 bool MouseEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
250 {
251     if (isSyntheticMouseEvent()) {
252         event()->eventPath().adjustForRelatedTarget(dispatcher->node(), event()->relatedTarget());
253         return dispatcher->dispatch();
254     }
255
256     if (isDisabledFormControl(dispatcher->node()))
257         return false;
258
259     if (event()->type().isEmpty())
260         return true; // Shouldn't happen.
261
262     ASSERT(!event()->target() || event()->target() != event()->relatedTarget());
263
264     EventTarget* relatedTarget = event()->relatedTarget();
265     event()->eventPath().adjustForRelatedTarget(dispatcher->node(), relatedTarget);
266
267     dispatcher->dispatch();
268     bool swallowEvent = event()->defaultHandled() || event()->defaultPrevented();
269
270     if (event()->type() != EventTypeNames::click || event()->detail() != 2)
271         return !swallowEvent;
272
273     // Special case: If it's a double click event, we also send the dblclick event. This is not part
274     // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated
275     // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same.
276     RefPtrWillBeRawPtr<MouseEvent> doubleClickEvent = MouseEvent::create();
277     doubleClickEvent->initMouseEvent(EventTypeNames::dblclick, event()->bubbles(), event()->cancelable(), event()->view(),
278                                      event()->detail(), event()->screenX(), event()->screenY(), event()->clientX(), event()->clientY(),
279                                      event()->ctrlKey(), event()->altKey(), event()->shiftKey(), event()->metaKey(),
280                                      event()->button(), relatedTarget);
281     if (event()->defaultHandled())
282         doubleClickEvent->setDefaultHandled();
283     EventDispatcher::dispatchEvent(dispatcher->node(), MouseEventDispatchMediator::create(doubleClickEvent));
284     if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
285         return false;
286     return !swallowEvent;
287 }
288
289 } // namespace blink