Android 触摸事件分离原理

什么是触摸事件分离?
屏幕上存在多个窗口时,多指触摸的情况下,多个手指的触摸事件可以分给不同的窗口,以下面的图为例,第一个手指按下,window1可以响应这个事件,第二个手指按下(第一个手指不松开),window2同样也可以响应第二个手指按下的事件,两个手指的触摸事件被分离到了不同的窗口,这就是触摸事件分离。
在这里插入图片描述
可以通过配置FLAG_SPLIT_TOUCH(0x00800000)这个flag来设置window是否支持事件分离。默认情况下,系统中的窗口都是支持分离的,所以默认情况下,上图的场景,window1和window2都可以收到触摸事件。

当然我们可以禁用window的事件分离功能,如在主配置文件中配置:

android:windowEnableSplitTouch="false"

只要window1和window2中的任意一个不支持触摸分离,触摸事件只会分发给第一个手指按下的window,第二个手指按下的window将不会接收到触摸事件。

事件分离的原理

这部分逻辑在InputDispatcher 的 findTouchedWindowTargetsLocked方法中,该方法用于查找目标窗口

int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
                                                        const MotionEntry& entry,
                                                        std::vector<InputTarget>& inputTargets,
                                                        nsecs_t* nextWakeupTime,
                                                        bool* outConflictingPointerActions) {
	//省略
	TouchState tempTouchState;
    std::unordered_map<int32_t, TouchState>::iterator oldStateIt =
            mTouchStatesByDisplay.find(displayId);
    if (oldStateIt != mTouchStatesByDisplay.end()) {
        oldState = &(oldStateIt->second);
        tempTouchState.copyFrom(*oldState);//将上次的信息拷贝到tempTouchState中
    }

	bool isSplit = tempTouchState.split;

	bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
                       maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction);//判断是否第一个手指按下

	if (newGesture) {//可以看出,第一个手指按下时,会清空tempTouchState,并将isSplit设为false
        bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
        //省略
        tempTouchState.reset();
        tempTouchState.down = down;
        tempTouchState.deviceId = entry.deviceId;
        tempTouchState.source = entry.source;
        tempTouchState.displayId = displayId;
        isSplit = false;
    }

	//省略
	if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {//1

		sp<InputWindowHandle> newTouchedWindowHandle =
                findTouchedWindowAtLocked(displayId, x, y, &tempTouchState,
                                          isDown /*addOutsideTargets*/, true /*addPortalWindows*/);//查找窗口
                                          
         // Figure out whether splitting will be allowed for this window.
        if (newTouchedWindowHandle != nullptr &&
            newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {//2,支持分离的话将isSplit 设为true
            // New window supports splitting, but we should never split mouse events.
            isSplit = !isFromMouse;
        } else if (isSplit) {// 3
            // New window does not support splitting but we have already split events.
            // Ignore the new window.
            newTouchedWindowHandle = nullptr;
        }

		// Handle the case where we did not find a window.
        if (newTouchedWindowHandle == nullptr) {
            // Try to assign the pointer to the first foreground window we find, if there is one.
            newTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle();//4
        }
		
		if (newTouchedWindowHandle != nullptr) {
			//省略
			 tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);//添加进目标窗口
		}
	}else{
		//省略
		//第二根手指按下并且按下的是不支持事件分离的window时,走这个逻辑
	}
	//省略
}

还是以上图为例,用情景分析的方式,分析下上面的代码逻辑

1,window1和window2都支持分离事件
第一个手指按下的时候,newGesture 为ture,先清空tempTouchState,然后进入注释1的分支,查找到window1窗口后,因为window1窗口支持事件分离,则进入注释2处分支,将isSplit 设为true。然后就是window1加入到tempTouchState中,该事件可分发至window1窗口
第二个手指按下的时候,先将上次的信息拷贝到tempTouchState中(上次将isSplit 设置为true了),所以此次isSplit 也为true,因为不是第一根手指按下newGesture 为false,所以不会清空tempTouchState,但因为是第二根手指按下且isSplit 为true,所以也会进入注释1的分支。查找到window2窗口后,因为window2也支持分离事件,所以也是进入注释2处的分支将isSplit 设为true,然后就是window2加入到tempTouchState中,该事件可分发至window2窗口
所以window1和window2都支持分离事件的话,两个窗口都可以响应对应的触摸事件

2,先按下的window1支持分离事件,window2不支持
第一个手指按下的时候,newGesture 为ture,先清空tempTouchState,然后进入注释1的分支,查找到window1窗口后,因为window1窗口支持事件分离,则进入注释2处分支,将isSplit 设为true。然后就是window1加入到tempTouchState中,该事件可分发至window1窗口
第二个手指按下的时候,先将上次的信息拷贝到tempTouchState中(上次将isSplit 设置为true了),所以此次isSplit 也为true,因为不是第一根手指按下newGesture 为false,所以不会清空tempTouchState,但因为是第二根手指按下且isSplit 为true,所以也会进入注释1的分支。查找到window2窗口后,因为window2不支持分离事件且isSplit 为true,所以这次是进入注释3处的分支又将newTouchedWindowHandle 设为null,所以window2并不会加入到tempTouchState中,该事件就不会分发至window2窗口
所以这种情况下,仅有window1能响应触摸事件,而window2不会响应第二根手指的触摸事件

3,先按下的window1不支持分离事件,window2支持
第一个手指按下的时候,newGesture 为ture,先清空tempTouchState,然后进入注释1的分支,查找到window1窗口后,因为window1窗口不支持事件分离,所以不会设置isSplit 的值,isSplit 还是为false。然后把window1加入到tempTouchState中,该事件可分发至window1窗口
第二个手指按下的时候,先将上次的信息拷贝到tempTouchState中,此次isSplit 还是为false,所以注释1的分支根本就不会进入。注释1处都不会进入的话,就不会去查找窗口,即不会找到window2,该事件就不会分发至window2窗口
所以这种情况下,也是仅有window1能响应触摸事件,而window2不会响应第二根手指的触摸事件

总结
分离事件的逻辑在findTouchedWindowTargetsLocked查找窗口的方法内。如果两个窗口中有一个不支持分离事件,那么只有先按下的那个窗口可以响应触摸事件,另一个窗口并不会响应后面手指的触摸事件。比如在分屏的场景下,如果我们想要在操作我们应用的时候,另一个应用不响应事件,就可以将我们的应用配置成不支持分离事件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/632269.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI应用案例:吸烟打电话行为识别推理

使用百度PaddlePaddle&#xff08;现更名为PaddlePaddle-GPU或PaddlePaddle-CPU&#xff09;框架来构建精准的人员抽烟、打电话动作识别模型&#xff0c;并将其应用于加油站监控场景&#xff0c;你可以遵循以下步骤&#xff1a; 数据准备&#xff1a; 收集抽烟和打电话行为的图…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑网络重构和应急资源的灾后配电网信息物理系统协调恢复方法》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

【Maven】Nexus私服简介_下载安装_登录

1、简介 1.1介绍 Nexus私服&#xff0c;也被称为Maven仓库管理器&#xff0c;是许多公司在自己的局域网内搭建的远程仓库服务器。提供了强大的仓库管理功能和构件搜索功能&#xff0c;使得开发人员能够更方便地管理和使用Maven项目中的依赖库。 1.2作用 内网访问&#xff1…

总台,电视台媒体邀约现场报道,应注意以下几点?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 邀请中央电视台&#xff08;总台&#xff09;这样的权威媒体来报道会议活动&#xff0c;需要注意以下几个关键要点&#xff1a; 提前规划&#xff1a;由于总台的新闻选题流程较为严格和…

2024CCPC郑州邀请赛暨河南省赛(A,B,C,D,F,G,H,J,K,L,M)

2024 National Invitational of CCPC (Zhengzhou), 2024 CCPC Henan Provincial Collegiate Programming Contest 2024 年中国大学生程序设计竞赛全国邀请赛&#xff08;郑州&#xff09;暨第六届 CCPC 河南省大学生程序设计竞赛 比赛链接 这场的题说实话难度其实都不大&…

24个AI写作网站汇总,免费ai工具,把AI用好工作效率真的能提高300%!

从去年到今年&#xff0c;可谓是AI爆发之年&#xff0c;各种AI工具也是层出不穷。随着openai的暴堆算力以及chatgpt人工智能算法的不断进步&#xff0c;ai正在大跨步的向前迈进。 ai可说是集中了全人类的智慧&#xff0c;未来ai的发展我是不敢想象的。不过在今天&#xff0c;如…

element select下拉框编辑时回显已经删除的数据

<el-form-item label"是否激活" prop"activationId"><el-selectv-model"formParams.activationId"style"width: 140px"clearableplaceholder"请选择"><el-optionv-for"item in activationList":ke…

CentOS7使用Docker安装Redis图文教程

1.拉取Redis镜像 这里制定了版本&#xff0c;不指定默认latest最新版 docker pull redis:6.0.8提示信息如下即为下载成功 2.上传配置文件 官方配置文件&#xff08;找自己对应的版本&#xff09;&#xff1a;reids.conf 或者将如下配置文件命名为redis.conf&#xff0c;上…

Kubernetes的Service类型详解

1. Service详解 1.1 Service介绍 在Kubernetes中&#xff0c;Service资源解决了Pod IP地址不固定的问题&#xff0c;提供了一种更稳定和可靠的服务访问方式。以下是Service的一些关键特性和工作原理&#xff1a; Service的稳定性&#xff1a;由于Pod可能会因为故障、重启或扩…

文件批量改名神器:轻松实现导入文件筛选与批量重命名,提升文件管理效率新体验!

电脑中的文件堆积如山&#xff0c;你是否曾为寻找某个特定文件而头疼不已&#xff1f;是否曾因为文件命名不规范而错失重要信息&#xff1f;别担心&#xff0c;现在有了这款文件批量改名神器&#xff0c;一切问题都将迎刃而解&#xff01; 第一步&#xff0c;我们打开需要改名文…

【ONE·基础算法 || 队列(宽搜运用) 优先级队列(堆运用) 】

总言 主要内容&#xff1a;编程题举例&#xff0c;熟悉理解宽搜类题型&#xff0c;队列、堆此类STL容器使用。       文章目录 总言1、 宽搜2、N 叉树的层序遍历&#xff08;medium&#xff09;2.1、题解 3、二叉树的锯齿形层序遍历&#xff08;medium&#xff09;3.1、题解…

【永洪BI】精确不同值计数

一、功能演示 二、使用说明 1、 功能简介 精确不同值计数&#xff0c;即统计所有数据行中不同数据值的总数量&#xff0c;数据值相同时只计算一次&#xff0c;如果存在维度字段&#xff0c;会按照不同类别分别计数。 2、 应用场景 想要统计数据中不同值出现的次数时可以使用…

Metasploit基本命令

1. 开启控制台 命令&#xff1a; msfconsole2. 搜索模块 命令&#xff1a; search ms17-010 # 模块名这里以搜索 ms17-010 为例&#xff0c; auxiliary 开头的为测试模块&#xff0c;也就是 POC&#xff0c;看看存不存在漏洞&#xff0c; exploit 开头的为攻击模块 3. 调…

DCMM(数据管理能力成熟度模型)对企业的价值

随着大数据时代的来临&#xff0c;数据已成为企业发展的重要驱动力。为了有效地管理和利用数据&#xff0c;企业需要建立一套完善的数据管理体系&#xff0c;而DCMM&#xff08;数据管理能力成熟度模型&#xff09;正是这样一个帮助企业构建和优化数据管理能力的框架。 DCMM结构…

芯片固定环氧胶有什么优点?

芯片固定环氧胶有什么优点&#xff1f; 芯片固定环氧胶在电子封装和芯片固定应用中具有多种显著优点&#xff0c;以下是其中的一些关键优势&#xff1a; 高粘接强度&#xff1a;环氧胶能够牢固地粘合芯片和基板&#xff0c;提供出色的粘接强度&#xff0c;确保芯片在各种环境条…

webpack优化构建速度示例-IgnorePlugin:

IgnorePlugin是webpack的一个内置插件&#xff0c;允许你忽略某些特定的模块或文件 webpack.config.jsconst config {entry: ./src/index.js,output: {filename: main.js},mode: development, }module.exports config;src/index.js import moment from moment console.log(mo…

剑指Offer打卡day34——AcWing 66. 两个链表的第一个公共结点

AcWing 66. 两个链表的第一个公共结点 暴力做法&#xff0c;两层for循环 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ class Solutio…

LeetCode109:组合总和Ⅳ

题目描述 给你一个由 不同 整数组成的数组 nums &#xff0c;和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 解题思想 使用完全背包 代码 /*dp[i]&#xff1a;表示装满容量为i的背包有dp[i]种方…

OpenHarmony上移植memtester

1. 下载源码&#xff1a; wget https://pyropus.ca./software/memtester/old-versions/memtester-4.6.0.tar.gz 2. 解压并指定交叉编译方式 解压 tar -xvf memtester-4.6.0.tar.gz 修改conf-cc和conf-ld&#xff0c;指定交叉编译方式 conf-cc conf-ld 3. 编译 直接运行m…

【问题实操】银河高级服务器操作系统实例分享,三台服务器宕机解决方式

1.服务器环境以及配置 物理机/虚拟机/云/容器 物理机 外网/私有网络/无网络 私有网络 处理器&#xff1a; Hygon C86 7265 24-core Processor 2 of 2 CPU sockets populated, 24 cores/48 threads per CPU 48 total cores, 96 total threads 内存&#xff1a; 768 GiB …