1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <ftl/flags.h>
20 #include <gui/WindowInfo.h>
21 #include <ui/Transform.h>
22 #include <utils/BitSet.h>
23 #include <bitset>
24 #include "Connection.h"
25 #include "InputTargetFlags.h"
26 
27 namespace android::inputdispatcher {
28 
29 /*
30  * An input target specifies how an input event is to be dispatched to a particular window
31  * including the window's input channel, control flags, a timeout, and an X / Y offset to
32  * be added to input event coordinates to compensate for the absolute position of the
33  * window area.
34  */
35 class InputTarget {
36 public:
37     using Flags = InputTargetFlags;
38 
39     enum class DispatchMode {
40         /* This flag indicates that the event should be sent as is.
41          * Should always be set unless the event is to be transmuted. */
42         AS_IS,
43         /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
44          * of the area of this target and so should instead be delivered as an
45          * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
46         OUTSIDE,
47         /* This flag indicates that a hover sequence is starting in the given window.
48          * The event is transmuted into ACTION_HOVER_ENTER. */
49         HOVER_ENTER,
50         /* This flag indicates that a hover event happened outside of a window which handled
51          * previous hover events, signifying the end of the current hover sequence for that
52          * window.
53          * The event is transmuted into ACTION_HOVER_ENTER. */
54         HOVER_EXIT,
55         /* This flag indicates that the event should be canceled.
56          * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
57          * outside of a window. */
58         SLIPPERY_EXIT,
59         /* This flag indicates that the event should be dispatched as an initial down.
60          * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
61          * into a new window. */
62         SLIPPERY_ENTER,
63 
64         ftl_last = SLIPPERY_ENTER,
65     };
66 
67     // The input connection to be targeted.
68     std::shared_ptr<Connection> connection;
69 
70     // Flags for the input target.
71     ftl::Flags<Flags> flags;
72 
73     // The dispatch mode that should be used for this target.
74     DispatchMode dispatchMode = DispatchMode::AS_IS;
75 
76     // Scaling factor to apply to MotionEvent as it is delivered.
77     // (ignored for KeyEvents)
78     float globalScaleFactor = 1.0f;
79 
80     // Current display transform. Used for compatibility for raw coordinates.
81     ui::Transform displayTransform;
82 
83     // Event time for the first motion event (ACTION_DOWN) dispatched to this input target if
84     // FLAG_SPLIT is set.
85     std::optional<nsecs_t> firstDownTimeInTarget;
86 
87     // The window that this input target is being dispatched to. It is possible for this to be
88     // null for cases like global monitors.
89     sp<gui::WindowInfoHandle> windowHandle;
90 
91     InputTarget() = default;
92     InputTarget(const std::shared_ptr<Connection>&, ftl::Flags<Flags> = {});
93 
94     android::base::Result<void> addPointers(std::bitset<MAX_POINTER_ID + 1> pointerIds,
95                                             const ui::Transform& transform);
96     void setDefaultPointerTransform(const ui::Transform& transform);
97 
98     /**
99      * Returns whether the default pointer information should be used. This will be true when the
100      * InputTarget doesn't have any bits set in the pointerIds bitset. This can happen for monitors
101      * and non splittable windows since we want all pointers for the EventEntry to go to this
102      * target.
103      */
104     bool useDefaultPointerTransform() const;
105 
106     /**
107      * Returns the default Transform object. This should be used when useDefaultPointerTransform is
108      * true.
109      */
110     const ui::Transform& getDefaultPointerTransform() const;
111 
112     const ui::Transform& getTransformForPointer(int32_t pointerId) const;
113 
114     std::bitset<MAX_POINTER_ID + 1> getPointerIds() const;
115 
116     std::string getPointerInfoString() const;
117 
118 private:
119     template <typename K, typename V>
120     using ArrayMap = std::vector<std::pair<K, V>>;
121     using PointerIds = std::bitset<MAX_POINTER_ID + 1>;
122     // The mapping of pointer IDs to the transform that should be used for that collection of IDs.
123     // Each of the pointer IDs are mutually disjoint, and their union makes up pointer IDs to
124     // include in the motion events dispatched to this target. We use an ArrayMap to store this to
125     // avoid having to define hash or comparison functions for ui::Transform, which would be needed
126     // to use std::unordered_map or std::map respectively.
127     ArrayMap<ui::Transform, PointerIds> mPointerTransforms;
128 };
129 
130 std::ostream& operator<<(std::ostream& out, const InputTarget& target);
131 
132 } // namespace android::inputdispatcher
133