1/*
2 * Copyright (C) 2010 Google Inc. All Rights Reserved.
3 * Copyright (C) 2017 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
28#pragma once
29
30#include "Node.h"
31
32namespace WebCore {
33
34class TouchList;
35
36class EventContext {
37 WTF_MAKE_FAST_ALLOCATED;
38public:
39 using EventInvokePhase = EventTarget::EventInvokePhase;
40
41 EventContext(Node*, EventTarget* currentTarget, EventTarget*, int closedShadowDepth);
42 virtual ~EventContext();
43
44 Node* node() const { return m_node.get(); }
45 EventTarget* currentTarget() const { return m_currentTarget.get(); }
46 EventTarget* target() const { return m_target.get(); }
47 int closedShadowDepth() const { return m_closedShadowDepth; }
48
49 virtual void handleLocalEvents(Event&, EventInvokePhase) const;
50
51 virtual bool isMouseOrFocusEventContext() const;
52 virtual bool isTouchEventContext() const;
53
54protected:
55#if !ASSERT_DISABLED
56 bool isUnreachableNode(EventTarget*) const;
57#endif
58
59 RefPtr<Node> m_node;
60 RefPtr<EventTarget> m_currentTarget;
61 RefPtr<EventTarget> m_target;
62 int m_closedShadowDepth { 0 };
63};
64
65class MouseOrFocusEventContext final : public EventContext {
66public:
67 MouseOrFocusEventContext(Node&, EventTarget* currentTarget, EventTarget*, int closedShadowDepth);
68 virtual ~MouseOrFocusEventContext();
69
70 Node* relatedTarget() const { return m_relatedTarget.get(); }
71 void setRelatedTarget(Node*);
72
73private:
74 void handleLocalEvents(Event&, EventInvokePhase) const final;
75 bool isMouseOrFocusEventContext() const final;
76
77 RefPtr<Node> m_relatedTarget;
78};
79
80#if ENABLE(TOUCH_EVENTS)
81
82class TouchEventContext final : public EventContext {
83public:
84 TouchEventContext(Node&, EventTarget* currentTarget, EventTarget*, int closedShadowDepth);
85 virtual ~TouchEventContext();
86
87 enum TouchListType { Touches, TargetTouches, ChangedTouches };
88 TouchList& touchList(TouchListType);
89
90private:
91 void handleLocalEvents(Event&, EventInvokePhase) const final;
92 bool isTouchEventContext() const final;
93
94 void checkReachability(const Ref<TouchList>&) const;
95
96 Ref<TouchList> m_touches;
97 Ref<TouchList> m_targetTouches;
98 Ref<TouchList> m_changedTouches;
99};
100
101#endif // ENABLE(TOUCH_EVENTS)
102
103#if !ASSERT_DISABLED
104
105inline bool EventContext::isUnreachableNode(EventTarget* target) const
106{
107 // FIXME: Checks also for SVG elements.
108 return is<Node>(target) && !downcast<Node>(*target).isSVGElement() && m_node->isClosedShadowHidden(downcast<Node>(*target));
109}
110
111#endif
112
113inline void MouseOrFocusEventContext::setRelatedTarget(Node* relatedTarget)
114{
115 ASSERT(!isUnreachableNode(relatedTarget));
116 m_relatedTarget = relatedTarget;
117}
118
119#if ENABLE(TOUCH_EVENTS)
120
121inline TouchList& TouchEventContext::touchList(TouchListType type)
122{
123 switch (type) {
124 case Touches:
125 return m_touches.get();
126 case TargetTouches:
127 return m_targetTouches.get();
128 case ChangedTouches:
129 return m_changedTouches.get();
130 }
131 ASSERT_NOT_REACHED();
132 return m_touches.get();
133}
134
135#endif
136
137#if ENABLE(TOUCH_EVENTS) && ASSERT_DISABLED
138
139inline void TouchEventContext::checkReachability(const Ref<TouchList>&) const
140{
141}
142
143#endif
144
145} // namespace WebCore
146
147SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::MouseOrFocusEventContext)
148static bool isType(const WebCore::EventContext& context) { return context.isMouseOrFocusEventContext(); }
149SPECIALIZE_TYPE_TRAITS_END()
150
151#if ENABLE(TOUCH_EVENTS)
152SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::TouchEventContext)
153static bool isType(const WebCore::EventContext& context) { return context.isTouchEventContext(); }
154SPECIALIZE_TYPE_TRAITS_END()
155#endif
156