Move occlusion detection into logical space
Same as our "hit test" to find the target window, since WM works in
logical space, we consider the window's frame to be (l, t, r, b), and
the portion of the window that can be occluded in the x-direction is
[l, r), and the portion of the window that can be occluded in the
y-direction is [t, b). When the logical space is different from the
physical space, the opening and closing intervals in each of these
directions will be inconsistent, leading to abnormal detection of the
edge part. Here we move the occlusion detection to the logical
space as well, consistent with the "hit test" for finding the target
window.
Bug: 327712879
Test: atest inputflinger_tests
Test: Create a window that can cause occlusion and perform clicks on the edges, making sure that the occlusion range is x = [l, r), y = [t, b) under each direction of the screen.
Signed-off-by: Linnan Li <lilinnan@xiaomi.corp-partner.google.com>
(cherry picked from https://partner-android-review.googlesource.com/q/commit:1a0060e9bcd25bee6ce7a9f5d01b9446b0c4d73b)
Merged-In: I19b739bc8f1e48d8bc70020a2b07da227eaa6d8b
Change-Id: I19b739bc8f1e48d8bc70020a2b07da227eaa6d8b
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 7f54bf1..5597613 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -573,6 +573,18 @@
return true;
}
+// Returns true if the given window's frame can occlude pointer events at the given display
+// location.
+bool windowOccludesTouchAt(const WindowInfo& windowInfo, int displayId, float x, float y,
+ const ui::Transform& displayTransform) {
+ if (windowInfo.displayId != displayId) {
+ return false;
+ }
+ const auto frame = displayTransform.transform(windowInfo.frame);
+ const auto p = floor(displayTransform.transform(x, y));
+ return p.x >= frame.left && p.x < frame.right && p.y >= frame.top && p.y < frame.bottom;
+}
+
bool isPointerFromStylus(const MotionEntry& entry, int32_t pointerIndex) {
return isFromSource(entry.source, AINPUT_SOURCE_STYLUS) &&
isStylusToolType(entry.pointerProperties[pointerIndex].toolType);
@@ -3056,7 +3068,7 @@
* If neither of those is true, then it means the touch can be allowed.
*/
InputDispatcher::TouchOcclusionInfo InputDispatcher::computeTouchOcclusionInfoLocked(
- const sp<WindowInfoHandle>& windowHandle, int32_t x, int32_t y) const {
+ const sp<WindowInfoHandle>& windowHandle, float x, float y) const {
const WindowInfo* windowInfo = windowHandle->getInfo();
int32_t displayId = windowInfo->displayId;
const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
@@ -3070,7 +3082,8 @@
break; // All future windows are below us. Exit early.
}
const WindowInfo* otherInfo = otherHandle->getInfo();
- if (canBeObscuredBy(windowHandle, otherHandle) && otherInfo->frameContainsPoint(x, y) &&
+ if (canBeObscuredBy(windowHandle, otherHandle) &&
+ windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId)) &&
!haveSameApplicationToken(windowInfo, otherInfo)) {
if (DEBUG_TOUCH_OCCLUSION) {
info.debugInfo.push_back(
@@ -3140,7 +3153,7 @@
}
bool InputDispatcher::isWindowObscuredAtPointLocked(const sp<WindowInfoHandle>& windowHandle,
- int32_t x, int32_t y) const {
+ float x, float y) const {
int32_t displayId = windowHandle->getInfo()->displayId;
const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId);
for (const sp<WindowInfoHandle>& otherHandle : windowHandles) {
@@ -3149,7 +3162,7 @@
}
const WindowInfo* otherInfo = otherHandle->getInfo();
if (canBeObscuredBy(windowHandle, otherHandle) &&
- otherInfo->frameContainsPoint(x, y)) {
+ windowOccludesTouchAt(*otherInfo, displayId, x, y, getTransformLocked(displayId))) {
return true;
}
}