blob: 35ad8587367eb992949159d660ee2285fc9efea9 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "InputTarget.h"
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <input/PrintTools.h>
#include <inttypes.h>
#include <string>
using android::base::StringPrintf;
namespace android::inputdispatcher {
namespace {
const static ui::Transform kIdentityTransform{};
}
InputTarget::InputTarget(const std::shared_ptr<Connection>& connection, ftl::Flags<Flags> flags)
: connection(connection), flags(flags) {}
void InputTarget::addPointers(std::bitset<MAX_POINTER_ID + 1> newPointerIds,
const ui::Transform& transform) {
// The pointerIds can be empty, but still a valid InputTarget. This can happen when there is no
// valid pointer property from the input event.
if (newPointerIds.none()) {
setDefaultPointerTransform(transform);
return;
}
// Ensure that the new set of pointers doesn't overlap with the current set of pointers.
if ((getPointerIds() & newPointerIds).any()) {
LOG(FATAL) << __func__ << " - overlap with incoming pointers "
<< bitsetToString(newPointerIds) << " in " << *this;
}
for (auto& [existingTransform, existingPointers] : mPointerTransforms) {
if (transform == existingTransform) {
existingPointers |= newPointerIds;
return;
}
}
mPointerTransforms.emplace_back(transform, newPointerIds);
}
void InputTarget::setDefaultPointerTransform(const ui::Transform& transform) {
mPointerTransforms = {{transform, {}}};
}
bool InputTarget::useDefaultPointerTransform() const {
return mPointerTransforms.size() <= 1;
}
const ui::Transform& InputTarget::getDefaultPointerTransform() const {
if (!useDefaultPointerTransform()) {
LOG(FATAL) << __func__ << ": Not using default pointer transform";
}
return mPointerTransforms.size() == 1 ? mPointerTransforms[0].first : kIdentityTransform;
}
const ui::Transform& InputTarget::getTransformForPointer(int32_t pointerId) const {
for (const auto& [transform, ids] : mPointerTransforms) {
if (ids.test(pointerId)) {
return transform;
}
}
LOG(FATAL) << __func__
<< ": Cannot get transform: The following Pointer ID does not exist in target: "
<< pointerId;
return kIdentityTransform;
}
std::string InputTarget::getPointerInfoString() const {
std::string out = "\n";
if (useDefaultPointerTransform()) {
const ui::Transform& transform = getDefaultPointerTransform();
transform.dump(out, "default", " ");
return out;
}
for (const auto& [transform, ids] : mPointerTransforms) {
const std::string name = "pointerIds " + bitsetToString(ids) + ":";
transform.dump(out, name.c_str(), " ");
}
return out;
}
std::bitset<MAX_POINTER_ID + 1> InputTarget::getPointerIds() const {
PointerIds allIds;
for (const auto& [_, ids] : mPointerTransforms) {
allIds |= ids;
}
return allIds;
}
std::ostream& operator<<(std::ostream& out, const InputTarget& target) {
out << "{connection=";
if (target.connection != nullptr) {
out << target.connection->getInputChannelName();
} else {
out << "<null>";
}
out << ", windowHandle=";
if (target.windowHandle != nullptr) {
out << target.windowHandle->getName();
} else {
out << "<null>";
}
out << ", dispatchMode=" << ftl::enum_string(target.dispatchMode).c_str();
out << ", targetFlags=" << target.flags.string();
out << ", pointers=" << target.getPointerInfoString();
out << "}";
return out;
}
} // namespace android::inputdispatcher