blob: cd0500c8722af8270cec94e0bf327f101c28a50e [file] [log] [blame]
/*
* Copyright (C) 2022 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 "TouchedWindow.h"
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <input/PrintTools.h>
using android::base::StringPrintf;
namespace android {
namespace inputdispatcher {
bool TouchedWindow::hasHoveringPointers() const {
for (const auto& [_, state] : mDeviceStates) {
if (state.hoveringPointerIds.any()) {
return true;
}
}
return false;
}
bool TouchedWindow::hasHoveringPointers(DeviceId deviceId) const {
const auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return false;
}
const DeviceState& state = stateIt->second;
return state.hoveringPointerIds.any();
}
void TouchedWindow::clearHoveringPointers(DeviceId deviceId) {
auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return;
}
DeviceState& state = stateIt->second;
state.hoveringPointerIds.reset();
if (!state.hasPointers()) {
mDeviceStates.erase(stateIt);
}
}
bool TouchedWindow::hasHoveringPointer(DeviceId deviceId, int32_t pointerId) const {
const auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return false;
}
const DeviceState& state = stateIt->second;
return state.hoveringPointerIds.test(pointerId);
}
void TouchedWindow::addHoveringPointer(DeviceId deviceId, int32_t pointerId) {
mDeviceStates[deviceId].hoveringPointerIds.set(pointerId);
}
void TouchedWindow::addTouchingPointers(DeviceId deviceId,
std::bitset<MAX_POINTER_ID + 1> pointers) {
mDeviceStates[deviceId].touchingPointerIds |= pointers;
}
bool TouchedWindow::hasTouchingPointers() const {
for (const auto& [_, state] : mDeviceStates) {
if (state.touchingPointerIds.any()) {
return true;
}
}
return false;
}
bool TouchedWindow::hasTouchingPointers(DeviceId deviceId) const {
return getTouchingPointers(deviceId).any();
}
bool TouchedWindow::hasTouchingPointer(DeviceId deviceId, int32_t pointerId) const {
return getTouchingPointers(deviceId).test(pointerId);
}
std::bitset<MAX_POINTER_ID + 1> TouchedWindow::getTouchingPointers(DeviceId deviceId) const {
const auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return {};
}
const DeviceState& state = stateIt->second;
return state.touchingPointerIds;
}
void TouchedWindow::removeTouchingPointer(DeviceId deviceId, int32_t pointerId) {
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(pointerId, true);
removeTouchingPointers(deviceId, pointerIds);
}
void TouchedWindow::removeTouchingPointers(DeviceId deviceId,
std::bitset<MAX_POINTER_ID + 1> pointers) {
const auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return;
}
DeviceState& state = stateIt->second;
state.touchingPointerIds &= ~pointers;
state.pilferingPointerIds &= ~pointers;
if (!state.hasPointers()) {
mDeviceStates.erase(stateIt);
}
}
std::set<DeviceId> TouchedWindow::getTouchingDeviceIds() const {
std::set<DeviceId> deviceIds;
for (const auto& [deviceId, deviceState] : mDeviceStates) {
if (deviceState.touchingPointerIds.any()) {
deviceIds.insert(deviceId);
}
}
return deviceIds;
}
bool TouchedWindow::hasPilferingPointers(DeviceId deviceId) const {
const auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return false;
}
const DeviceState& state = stateIt->second;
return state.pilferingPointerIds.any();
}
void TouchedWindow::addPilferingPointers(DeviceId deviceId,
std::bitset<MAX_POINTER_ID + 1> pointerIds) {
mDeviceStates[deviceId].pilferingPointerIds |= pointerIds;
}
void TouchedWindow::addPilferingPointer(DeviceId deviceId, int32_t pointerId) {
mDeviceStates[deviceId].pilferingPointerIds.set(pointerId);
}
std::bitset<MAX_POINTER_ID + 1> TouchedWindow::getPilferingPointers(DeviceId deviceId) const {
const auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return {};
}
const DeviceState& state = stateIt->second;
return state.pilferingPointerIds;
}
std::map<DeviceId, std::bitset<MAX_POINTER_ID + 1>> TouchedWindow::getPilferingPointers() const {
std::map<DeviceId, std::bitset<MAX_POINTER_ID + 1>> out;
for (const auto& [deviceId, state] : mDeviceStates) {
out.emplace(deviceId, state.pilferingPointerIds);
}
return out;
}
std::optional<nsecs_t> TouchedWindow::getDownTimeInTarget(DeviceId deviceId) const {
const auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return {};
}
const DeviceState& state = stateIt->second;
return state.downTimeInTarget;
}
void TouchedWindow::trySetDownTimeInTarget(DeviceId deviceId, nsecs_t downTime) {
auto [stateIt, _] = mDeviceStates.try_emplace(deviceId);
DeviceState& state = stateIt->second;
if (!state.downTimeInTarget) {
state.downTimeInTarget = downTime;
}
}
void TouchedWindow::removeAllTouchingPointersForDevice(DeviceId deviceId) {
const auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return;
}
DeviceState& state = stateIt->second;
state.touchingPointerIds.reset();
state.pilferingPointerIds.reset();
state.downTimeInTarget.reset();
if (!state.hasPointers()) {
mDeviceStates.erase(stateIt);
}
}
void TouchedWindow::removeHoveringPointer(DeviceId deviceId, int32_t pointerId) {
const auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return;
}
DeviceState& state = stateIt->second;
state.hoveringPointerIds.set(pointerId, false);
if (!state.hasPointers()) {
mDeviceStates.erase(stateIt);
}
}
void TouchedWindow::removeAllHoveringPointersForDevice(DeviceId deviceId) {
const auto stateIt = mDeviceStates.find(deviceId);
if (stateIt == mDeviceStates.end()) {
return;
}
DeviceState& state = stateIt->second;
state.hoveringPointerIds.reset();
if (!state.hasPointers()) {
mDeviceStates.erase(stateIt);
}
}
std::string TouchedWindow::deviceStateToString(const TouchedWindow::DeviceState& state) {
return StringPrintf("[touchingPointerIds=%s, "
"downTimeInTarget=%s, hoveringPointerIds=%s, pilferingPointerIds=%s]",
bitsetToString(state.touchingPointerIds).c_str(),
toString(state.downTimeInTarget).c_str(),
bitsetToString(state.hoveringPointerIds).c_str(),
bitsetToString(state.pilferingPointerIds).c_str());
}
std::string TouchedWindow::dump() const {
std::string out;
std::string deviceStates =
dumpMap(mDeviceStates, constToString, TouchedWindow::deviceStateToString);
out += StringPrintf("name='%s', targetFlags=%s, mDeviceStates=%s\n",
windowHandle->getName().c_str(), targetFlags.string().c_str(),
deviceStates.c_str());
return out;
}
std::ostream& operator<<(std::ostream& out, const TouchedWindow& window) {
out << window.dump();
return out;
}
} // namespace inputdispatcher
} // namespace android