b875392efae6270299157517467d31203ea4265d
[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, event.syntheticEventType());
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, PlatformMouseEvent::SyntheticEventType syntheticEventType)
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, syntheticEventType));
78 }
79
80 MouseEvent::MouseEvent()
81     : m_button(0)
82     , m_buttonDown(false)
83 {
84 }
85
86 MouseEvent::MouseEvent(const AtomicString& eventType, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<AbstractView> view,
87     int detail, int screenX, int screenY, int pageX, int pageY,
88     int movementX, int movementY,
89     bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
90     unsigned short button, PassRefPtrWillBeRawPtr<EventTarget> relatedTarget,
91     PassRefPtrWillBeRawPtr<DataTransfer> dataTransfer, bool isSimulated, PlatformMouseEvent::SyntheticEventType syntheticEventType)
92     : MouseRelatedEvent(eventType, canBubble, cancelable, view, detail, IntPoint(screenX, screenY),
93                         IntPoint(pageX, pageY),
94                         IntPoint(movementX, movementY),
95                         ctrlKey, altKey, shiftKey, metaKey, isSimulated)
96     , m_button(button == (unsigned short)-1 ? 0 : button)
97     , m_buttonDown(button != (unsigned short)-1)
98     , m_relatedTarget(relatedTarget)
99     , m_dataTransfer(dataTransfer)
100     , m_syntheticEventType(syntheticEventType)
101 {
102 }
103
104 MouseEvent::MouseEvent(const AtomicString& eventType, const MouseEventInit& initializer)
105     : MouseRelatedEvent(eventType, initializer.bubbles, initializer.cancelable, initializer.view, initializer.detail, IntPoint(initializer.screenX, initializer.screenY),
106         IntPoint(0 /* pageX */, 0 /* pageY */),
107         IntPoint(0 /* movementX */, 0 /* movementY */),
108         initializer.ctrlKey, initializer.altKey, initializer.shiftKey, initializer.metaKey, false /* isSimulated */)
109     , m_button(initializer.button == (unsigned short)-1 ? 0 : initializer.button)
110     , m_buttonDown(initializer.button != (unsigned short)-1)
111     , m_relatedTarget(initializer.relatedTarget)
112     , m_dataTransfer(nullptr)
113 {
114     initCoordinates(IntPoint(initializer.clientX, initializer.clientY));
115 }
116
117 MouseEvent::~MouseEvent()
118 {
119 }
120
121 void MouseEvent::initMouseEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtrWillBeRawPtr<AbstractView> view,
122                                 int detail, int screenX, int screenY, int clientX, int clientY,
123                                 bool ctrlKey, bool altKey, bool shiftKey, bool metaKey,
124                                 unsigned short button, PassRefPtrWillBeRawPtr<EventTarget> relatedTarget)
125 {
126     if (dispatched())
127         return;
128
129     initUIEvent(type, canBubble, cancelable, view, detail);
130
131     m_screenLocation = IntPoint(screenX, screenY);
132     m_ctrlKey = ctrlKey;
133     m_altKey = altKey;
134     m_shiftKey = shiftKey;
135     m_metaKey = metaKey;
136     m_button = button == (unsigned short)-1 ? 0 : button;
137     m_buttonDown = button != (unsigned short)-1;
138     m_relatedTarget = relatedTarget;
139
140     initCoordinates(IntPoint(clientX, clientY));
141
142     // FIXME: m_isSimulated is not set to false here.
143     // FIXME: m_dataTransfer is not set to nullptr here.
144 }
145
146 const AtomicString& MouseEvent::interfaceName() const
147 {
148     return EventNames::MouseEvent;
149 }
150
151 bool MouseEvent::isMouseEvent() const
152 {
153     return true;
154 }
155
156 bool MouseEvent::isDragEvent() const
157 {
158     const AtomicString& t = type();
159     return t == EventTypeNames::dragenter || t == EventTypeNames::dragover || t == EventTypeNames::dragleave || t == EventTypeNames::drop
160                || t == EventTypeNames::dragstart|| t == EventTypeNames::drag || t == EventTypeNames::dragend;
161 }
162
163 int MouseEvent::which() const
164 {
165     // For the DOM, the return values for left, middle and right mouse buttons are 0, 1, 2, respectively.
166     // For the Netscape "which" property, the return values for left, middle and right mouse buttons are 1, 2, 3, respectively.
167     // So we must add 1.
168     if (!m_buttonDown)
169         return 0;
170     return m_button + 1;
171 }
172
173 Node* MouseEvent::toElement() const
174 {
175     // MSIE extension - "the object toward which the user is moving the mouse pointer"
176     if (type() == EventTypeNames::mouseout || type() == EventTypeNames::mouseleave)
177         return relatedTarget() ? relatedTarget()->toNode() : 0;
178
179     return target() ? target()->toNode() : 0;
180 }
181
182 Node* MouseEvent::fromElement() const
183 {
184     // MSIE extension - "object from which activation or the mouse pointer is exiting during the event" (huh?)
185     if (type() != EventTypeNames::mouseout && type() != EventTypeNames::mouseleave)
186         return relatedTarget() ? relatedTarget()->toNode() : 0;
187
188     return target() ? target()->toNode() : 0;
189 }
190
191 void MouseEvent::trace(Visitor* visitor)
192 {
193     visitor->trace(m_relatedTarget);
194     visitor->trace(m_dataTransfer);
195     MouseRelatedEvent::trace(visitor);
196 }
197
198 PassRefPtrWillBeRawPtr<SimulatedMouseEvent> SimulatedMouseEvent::create(const AtomicString& eventType, PassRefPtrWillBeRawPtr<AbstractView> view, PassRefPtrWillBeRawPtr<Event> underlyingEvent)
199 {
200     return adoptRefWillBeNoop(new SimulatedMouseEvent(eventType, view, underlyingEvent));
201 }
202
203 SimulatedMouseEvent::~SimulatedMouseEvent()
204 {
205 }
206
207 SimulatedMouseEvent::SimulatedMouseEvent(const AtomicString& eventType, PassRefPtrWillBeRawPtr<AbstractView> view, PassRefPtrWillBeRawPtr<Event> underlyingEvent)
208     : MouseEvent(eventType, true, true, view, 0, 0, 0, 0, 0, 0, 0, false, false, false, false, 0,
209         nullptr, nullptr, true, PlatformMouseEvent::RealOrIndistinguishable)
210 {
211     if (UIEventWithKeyState* keyStateEvent = findEventWithKeyState(underlyingEvent.get())) {
212         m_ctrlKey = keyStateEvent->ctrlKey();
213         m_altKey = keyStateEvent->altKey();
214         m_shiftKey = keyStateEvent->shiftKey();
215         m_metaKey = keyStateEvent->metaKey();
216     }
217     setUnderlyingEvent(underlyingEvent);
218
219     if (this->underlyingEvent() && this->underlyingEvent()->isMouseEvent()) {
220         MouseEvent* mouseEvent = toMouseEvent(this->underlyingEvent());
221         m_screenLocation = mouseEvent->screenLocation();
222         initCoordinates(mouseEvent->clientLocation());
223     }
224 }
225
226 void SimulatedMouseEvent::trace(Visitor* visitor)
227 {
228     MouseEvent::trace(visitor);
229 }
230
231 PassRefPtrWillBeRawPtr<MouseEventDispatchMediator> MouseEventDispatchMediator::create(PassRefPtrWillBeRawPtr<MouseEvent> mouseEvent, MouseEventType mouseEventType)
232 {
233     return adoptRefWillBeNoop(new MouseEventDispatchMediator(mouseEvent, mouseEventType));
234 }
235
236 MouseEventDispatchMediator::MouseEventDispatchMediator(PassRefPtrWillBeRawPtr<MouseEvent> mouseEvent, MouseEventType mouseEventType)
237     : EventDispatchMediator(mouseEvent), m_mouseEventType(mouseEventType)
238 {
239 }
240
241 MouseEvent* MouseEventDispatchMediator::event() const
242 {
243     return toMouseEvent(EventDispatchMediator::event());
244 }
245
246 bool MouseEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
247 {
248     if (isSyntheticMouseEvent()) {
249         event()->eventPath().adjustForRelatedTarget(dispatcher->node(), event()->relatedTarget());
250         return dispatcher->dispatch();
251     }
252
253     if (isDisabledFormControl(dispatcher->node()))
254         return false;
255
256     if (event()->type().isEmpty())
257         return true; // Shouldn't happen.
258
259     ASSERT(!event()->target() || event()->target() != event()->relatedTarget());
260
261     EventTarget* relatedTarget = event()->relatedTarget();
262     event()->eventPath().adjustForRelatedTarget(dispatcher->node(), relatedTarget);
263
264     dispatcher->dispatch();
265     bool swallowEvent = event()->defaultHandled() || event()->defaultPrevented();
266
267     if (event()->type() != EventTypeNames::click || event()->detail() != 2)
268         return !swallowEvent;
269
270     // Special case: If it's a double click event, we also send the dblclick event. This is not part
271     // of the DOM specs, but is used for compatibility with the ondblclick="" attribute. This is treated
272     // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same.
273     RefPtrWillBeRawPtr<MouseEvent> doubleClickEvent = MouseEvent::create();
274     doubleClickEvent->initMouseEvent(EventTypeNames::dblclick, event()->bubbles(), event()->cancelable(), event()->view(),
275                                      event()->detail(), event()->screenX(), event()->screenY(), event()->clientX(), event()->clientY(),
276                                      event()->ctrlKey(), event()->altKey(), event()->shiftKey(), event()->metaKey(),
277                                      event()->button(), relatedTarget);
278     if (event()->defaultHandled())
279         doubleClickEvent->setDefaultHandled();
280     EventDispatcher::dispatchEvent(dispatcher->node(), MouseEventDispatchMediator::create(doubleClickEvent));
281     if (doubleClickEvent->defaultHandled() || doubleClickEvent->defaultPrevented())
282         return false;
283     return !swallowEvent;
284 }
285
286 } // namespace blink