Slion / Fulguris

⚡Web Browser
http://fulguris.slions.net
Other
489 stars 48 forks source link

Tab animation crash when mouse hover #599

Closed Slion closed 8 months ago

Slion commented 8 months ago

If you mouse hover the WebView during tab change animation you can get the following crash. For instance on a device with a keyboard and mouse just do Ctrl+Tab while moving the mouse of the web page. This is related to #579.

java.lang.IndexOutOfBoundsException: getChildDrawingOrder() returned invalid index 1 (child count is 1)
    at android.view.ViewGroup.getAndVerifyPreorderedIndex(ViewGroup.java:2099)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2055)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewGroup.dispatchResolvePointerIcon(ViewGroup.java:2088)
    at android.view.ViewGroup.onResolvePointerIcon(ViewGroup.java:2063)
    at android.view.ViewRootImpl.updatePointerIcon(ViewRootImpl.java:6860)
    at android.view.ViewRootImpl.-$$Nest$mupdatePointerIcon(Unknown Source:0)
    at android.view.ViewRootImpl$ViewPostImeInputStage.maybeUpdatePointerIcon(ViewRootImpl.java:6801)
    at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6779)
    at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6578)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6034)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6091)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6057)
    at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:6222)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6065)
    at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:6279)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6038)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6091)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6057)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6065)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6038)
    at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:9206)
    at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:9157)
    at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:9126)
    at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:9329)
    at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:267)
    at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
    at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:247)
    at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:9286)
    at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:9420)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1231)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
    at android.view.Choreographer.doCallbacks(Choreographer.java:899)
    at android.view.Choreographer.doFrame(Choreographer.java:824)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
    at android.os.Handler.handleCallback(Handler.java:942)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:7918)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Slion commented 8 months ago

This is a massive bug in Android where the motion event processing can't deal with changes in the view hierarchy. That means you just cant safely remove views past the creation of your activity.

The crash above can be worked around by doing something like that in a custom ViewGroup:

    override fun onResolvePointerIcon(event: MotionEvent?, pointerIndex: Int): PointerIcon? {

        var icon: PointerIcon? = null

        try {
            icon = super.onResolvePointerIcon(event, pointerIndex)
        }
        catch (ex: Exception) {
            Timber.w(ex,"Pointer icon exception")
        }

        return icon
    }

Unfortunately it then crashes the same way down from ViewRootImpl.maybeUpdateTooltip and we can't override ViewGroup.dispatchTooltipHoverEvent cause the dickheads at Android think so big of themselves they need to lock every freaking APIs you should not be using. I would need to be able to override those APIs to workaround Android bugs but I can't because they decided it would be unsafe for you to do that 😭