Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 21a41f99 authored by Miranda Kephart's avatar Miranda Kephart
Browse files

Monitor screenshot shelf view for outside touch events

We need to release focus on the screenshot window when we get outside
touches to allow the keyboard to come out (e.g. when taking a screenshot
on lockscreen).

Flag: com.android.systemui.screenshot_shelf_ui2
Bug: 329659738
Bug: 339591708
Fix: 339591708
Test: set screen lock to password, verify that taking a screenshot on
lockscreen and tapping the preview allows the keyboard to come up for
unlock

Change-Id: Icce3c28351382d65c24343cb60dd4103242dfccc
parent 64d7a085
Loading
Loading
Loading
Loading
+53 −8
Original line number Diff line number Diff line
@@ -22,8 +22,13 @@ import android.app.Notification
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Rect
import android.graphics.Region
import android.os.Looper
import android.view.Choreographer
import android.view.InputEvent
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.ScrollCaptureResponse
import android.view.View
import android.view.ViewTreeObserver
@@ -48,6 +53,8 @@ import com.android.systemui.screenshot.ui.ScreenshotShelfView
import com.android.systemui.screenshot.ui.binder.ScreenshotShelfViewBinder
import com.android.systemui.screenshot.ui.viewmodel.AnimationState
import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel
import com.android.systemui.shared.system.InputChannelCompat
import com.android.systemui.shared.system.InputMonitorCompat
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -91,6 +98,8 @@ constructor(
    override var isPendingSharedTransition = false

    private val animationController = ScreenshotAnimationController(view, viewModel)
    private var inputMonitor: InputMonitorCompat? = null
    private var inputEventReceiver: InputChannelCompat.InputEventReceiver? = null

    init {
        shelfViewBinder.bind(
@@ -106,20 +115,25 @@ constructor(
        setOnKeyListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) }
        debugLog(DEBUG_WINDOW) { "adding OnComputeInternalInsetsListener" }
        view.viewTreeObserver.addOnComputeInternalInsetsListener { info ->
            val touchableRegion =
                view.getTouchRegion(
                    windowManager.currentWindowMetrics.windowInsets.getInsets(
                        WindowInsets.Type.systemGestures()
                    )
                )
            info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION)
            info.touchableRegion.set(touchableRegion)
            info.touchableRegion.set(getTouchRegion())
        }
        screenshotPreview = view.screenshotPreview
        thumbnailObserver.setViews(
            view.blurredScreenshotPreview,
            view.requireViewById(R.id.screenshot_preview_border)
        )
        view.addOnAttachStateChangeListener(
            object : View.OnAttachStateChangeListener {
                override fun onViewAttachedToWindow(v: View) {
                    startInputListening()
                }

                override fun onViewDetachedFromWindow(v: View) {
                    stopInputListening()
                }
            }
        )
    }

    override fun reset() {
@@ -236,7 +250,12 @@ constructor(
        callbacks?.onUserInteraction() // reset the timeout
    }

    override fun stopInputListening() {}
    override fun stopInputListening() {
        inputMonitor?.dispose()
        inputMonitor = null
        inputEventReceiver?.dispose()
        inputEventReceiver = null
    }

    override fun requestFocus() {
        view.requestFocus()
@@ -303,6 +322,32 @@ constructor(
        )
    }

    private fun startInputListening() {
        stopInputListening()
        inputMonitor =
            InputMonitorCompat("Screenshot", displayId).also {
                inputEventReceiver =
                    it.getInputReceiver(Looper.getMainLooper(), Choreographer.getInstance()) {
                        ev: InputEvent? ->
                        if (
                            ev is MotionEvent &&
                                ev.actionMasked == MotionEvent.ACTION_DOWN &&
                                !getTouchRegion().contains(ev.rawX.toInt(), ev.rawY.toInt())
                        ) {
                            callbacks?.onTouchOutside()
                        }
                    }
            }
    }

    private fun getTouchRegion(): Region {
        return view.getTouchRegion(
            windowManager.currentWindowMetrics.windowInsets.getInsets(
                WindowInsets.Type.systemGestures()
            )
        )
    }

    @AssistedFactory
    interface Factory : ScreenshotViewProxy.Factory {
        override fun getProxy(context: Context, displayId: Int): ScreenshotShelfViewProxy