码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【input系统】MotionEvent的分解


    在打开多窗口的时候,比如A,B两个应用窗口,我们通过onTouchEvent查看log可以发现,在A窗口上的点击事件不会传给B窗口,当有多个点击事件时,A,B接收到的事件是不一样的,也就是说,在InputDispatcher的notifyMotion中的一个MotionEvent,在传送给app的时候,会根据窗口进行拆分。

        
        
        
        
        
        
        

    这个处理是splitMotionEvent方法,

    2317InputDispatcher::MotionEntry*
    2318InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
    2319    ALOG_ASSERT(pointerIds.value != 0);
    2320
    2321    uint32_t splitPointerIndexMap[MAX_POINTERS];
    2322    PointerProperties splitPointerProperties[MAX_POINTERS];
    2323    PointerCoords splitPointerCoords[MAX_POINTERS];
    2324
    2325    uint32_t originalPointerCount = originalMotionEntry->pointerCount;
    2326    uint32_t splitPointerCount = 0;
    2327
    2328    for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
    2329            originalPointerIndex++) {
    2330        const PointerProperties& pointerProperties =
    2331                originalMotionEntry->pointerProperties[originalPointerIndex];
    2332        uint32_t pointerId = uint32_t(pointerProperties.id);
    2333        if (pointerIds.hasBit(pointerId)) {
    2334            splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
    2335            splitPointerProperties[splitPointerCount].copyFrom(pointerProperties);
    2336            splitPointerCoords[splitPointerCount].copyFrom(
    2337                    originalMotionEntry->pointerCoords[originalPointerIndex]);
    2338            splitPointerCount += 1;
    2339        }
    2340    }
    2341
    2342    if (splitPointerCount != pointerIds.count()) {
    2343        // This is bad.  We are missing some of the pointers that we expected to deliver.
    2344        // Most likely this indicates that we received an ACTION_MOVE events that has
    2345        // different pointer ids than we expected based on the previous ACTION_DOWN
    2346        // or ACTION_POINTER_DOWN events that caused us to decide to split the pointers
    2347        // in this way.
    2348        ALOGW("Dropping split motion event because the pointer count is %d but "
    2349                "we expected there to be %d pointers.  This probably means we received "
    2350                "a broken sequence of pointer ids from the input device.",
    2351                splitPointerCount, pointerIds.count());
    2352        return NULL;
    2353    }
    2354
    2355    int32_t action = originalMotionEntry->action;
    2356    int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
    2357    if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
    2358            || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
    2359        int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
    2360        const PointerProperties& pointerProperties =
    2361                originalMotionEntry->pointerProperties[originalPointerIndex];
    2362        uint32_t pointerId = uint32_t(pointerProperties.id);
    2363        if (pointerIds.hasBit(pointerId)) {
    2364            if (pointerIds.count() == 1) {
    2365                // The first/last pointer went down/up.
    2366                action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
    2367                        ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
    2368            } else {
    2369                // A secondary pointer went down/up.
    2370                uint32_t splitPointerIndex = 0;
    2371                while (pointerId != uint32_t(splitPointerProperties[splitPointerIndex].id)) {
    2372                    splitPointerIndex += 1;
    2373                }
    2374                action = maskedAction | (splitPointerIndex
    2375                        << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
    2376            }
    2377        } else {
    2378            // An unrelated pointer changed.
    2379            action = AMOTION_EVENT_ACTION_MOVE;
    2380        }
    2381    }
    2382
    2383    MotionEntry* splitMotionEntry = new MotionEntry(
    2384            originalMotionEntry->eventTime,
    2385            originalMotionEntry->deviceId,
    2386            originalMotionEntry->source,
    2387            originalMotionEntry->policyFlags,
    2388            action,
    2389            originalMotionEntry->actionButton,
    2390            originalMotionEntry->flags,
    2391            originalMotionEntry->metaState,
    2392            originalMotionEntry->buttonState,
    2393            originalMotionEntry->edgeFlags,
    2394            originalMotionEntry->xPrecision,
    2395            originalMotionEntry->yPrecision,
    2396            originalMotionEntry->downTime,
    2397            originalMotionEntry->displayId,
    2398            splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0);
    2399
    2400    if (originalMotionEntry->injectionState) {
    2401        splitMotionEntry->injectionState = originalMotionEntry->injectionState;
    2402        splitMotionEntry->injectionState->refCount += 1;
    2403    }
    2404
    2405    return splitMotionEntry;

    其调用流程是

    dispatchMotionLocked

    dispatchEventLocked

    prepareDispatchCycleLocked
    
    splitMotionEvent
    主要是区别出各窗口上的点,根据pointID来进行拆分,具体的分析可以参考
    ViewGroup事件分发总结-多点触摸事件拆分 - 掘金
    在应用中也有类似的拆分处理,

    可以看出,touch事件(MotionEvent)的传送多么的不容易,那么多的操作,多次加工,千辛万苦才传给了接收者。这一路,太辛苦。

  • 相关阅读:
    利用CompletableFuture提高接口的响应速度
    25 avl树
    【博学谷学习记录】超强总结,用心分享丨大数据超神之路(四):shell脚本
    Rust 语言学习杂谈 (end) (各种工作中遇到的疑难杂症)
    react路由v6版本NavLink的两个小坑及解决
    常见服务器操作系统有哪些
    线性回归介绍以及实现
    24校招总结
    用delphi7将excel导入access并查询及其分析(一)
    LLVM学习笔记(59)
  • 原文地址:https://blog.csdn.net/aaajj/article/details/127097807
  • 最新文章
  • 沪漂五周年了:我越来越迷茫了
    Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
    MySQL-Seconds_behind_master的精度误差
    [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
    AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
    Agent OS :五种驯服不确定性的范式
    PortSwigger SQL注入LAB11
    数据库即时编译JIT
    [Begin]AI Learn Data Day 0
    深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号