Merge "Input: Handle parent surface crops 1/2"
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index d8702e5..045db31 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -72,6 +72,14 @@
     return *this;
 }
 
+Rect& Rect::inset(int32_t left, int32_t top, int32_t right, int32_t bottom) {
+    this->left += left;
+    this->top += top;
+    this->right -= right;
+    this->bottom -= bottom;
+    return *this;
+}
+
 const Rect Rect::operator +(const Point& rhs) const {
     const Rect result(left + rhs.x, top + rhs.y, right + rhs.x, bottom + rhs.y);
     return result;
diff --git a/libs/ui/include/ui/Rect.h b/libs/ui/include/ui/Rect.h
index 0bec0b7..9edb510 100644
--- a/libs/ui/include/ui/Rect.h
+++ b/libs/ui/include/ui/Rect.h
@@ -120,7 +120,7 @@
         right = rb.x;
         bottom = rb.y;
     }
-    
+
     // the following 4 functions return the 4 corners of the rect as Point
     Point leftTop() const {
         return Point(left, top);
@@ -175,6 +175,11 @@
     Rect& offsetTo(int32_t x, int32_t y);
     Rect& offsetBy(int32_t x, int32_t y);
 
+    /**
+     * Insets the rectangle on all sides specified by the insets.
+     */
+    Rect& inset(int32_t left, int32_t top, int32_t right, int32_t bottom);
+
     bool intersect(const Rect& with, Rect* result) const;
 
     // Create a new Rect by transforming this one using a graphics HAL
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 15e416a..f53ffae 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2121,10 +2121,6 @@
 
 InputWindowInfo Layer::fillInputInfo(const Rect& screenBounds) {
     InputWindowInfo info = mDrawingState.inputInfo;
-    info.frameLeft = screenBounds.left + info.surfaceInset;
-    info.frameTop = screenBounds.top + info.surfaceInset;
-    info.frameRight = screenBounds.right - info.surfaceInset;
-    info.frameBottom = screenBounds.bottom - info.surfaceInset;
 
     ui::Transform t = getTransform();
     const float xScale = t.sx();
@@ -2135,9 +2131,26 @@
         info.touchableRegion.scaleSelf(xScale, yScale);
     }
 
-    info.touchableRegion = info.touchableRegion.translate(
-            screenBounds.left,
-            screenBounds.top);
+    // Transform layer size to screen space and inset it by surface insets.
+    Rect layerBounds = getCroppedBufferSize(getDrawingState());
+    layerBounds = t.transform(layerBounds);
+    layerBounds.inset(info.surfaceInset, info.surfaceInset, info.surfaceInset, info.surfaceInset);
+
+    // Intersect with screen bounds to shrink the frame by the surface insets. The surface insets
+    // are not set on the screen bounds directly since the surface inset region may already be
+    // cropped by a parent layer.
+    Rect frame;
+    screenBounds.intersect(layerBounds, &frame);
+
+    info.frameLeft = frame.left;
+    info.frameTop = frame.top;
+    info.frameRight = frame.right;
+    info.frameBottom = frame.bottom;
+
+    // Position the touchable region relative to frame screen location and restrict it to frame
+    // bounds.
+    info.touchableRegion = info.touchableRegion.translate(info.frameLeft, info.frameTop);
+    info.touchableRegion = info.touchableRegion.intersect(frame);
     info.visible = isVisible();
     return info;
 }