1.MotionEventçgetActionãgetActionMaskågetActionIndexçåºå«
2.Android Touch事件InputManagerService源码解析(二)
3.UE4-Slate源码学习(四)FSceneViewport
4.android onTouchEventåsetOnTouchListenerä¸onTouchçåºå«
5.linux内核hid触摸源码hid-multitouch.c剖析
6.UE4-Slate源码学习(二)slate事件触发
MotionEventçgetActionãgetActionMaskågetActionIndexçåºå«
å¨å¾å¤èªå®ä¹Viewçåºæ¯ä¸ï¼é½æå¯è½éè¦éåonTouchEventãdispatchTouchEventçæ¹æ³ï¼è¿äºæ¹æ³é½ä¼ å ¥ä¸ä¸ªMotionEvent对象ï¼ä¸è¬æ¥è¯´ï¼æ们éè¦éè¿è¯¥MotionEvent对象æ¥è·åå½åçæå¿å¨ä½ï¼ç¶åå¤æAction_DownãAction_MoveãAction_Upæ¥æ§è¡ä¸åçæä½é»è¾ãä½æ¯å½æ们çMotionEvent对象æ¶ï¼åç°å®ægetActionãgetActionMaskågetActionIndexæ¹æ³ï¼èä¸å¨æ们ç第ä¸æ¹æºç æ¶ï¼ç»å¸¸ä¼çå°è¿æ ·çåæ³ï¼
åæ¶ä¹ä¼çå°è¿æ ·çåæ³ï¼
è¿ä¸¤ç§åæ³å°åºæä»ä¹åºå«å¢ï¼æ们就æ¥è¯´ä¸ä¸MotionEventçå ç§è·åActionä¿¡æ¯çæ¹æ³ã
Androidç¨ä¸ä¸ªä½çæ´æ°å¼æ¥è¡¨ç¤ºä¸ä¸ªTouchEventäºä»¶ï¼ä½8ä½è¡¨ç¤ºTouchäºä»¶çå ·ä½å¨ä½ï¼ä¾å¦æä¸ãæ¬èµ·ã移å¨çå¨ä½ãé«8ä½è¡¨ç¤ºTouchäºä»¶ä¸å¤ç¹è§¦æ§çç´¢å¼å¼ã
ä»æºç å¯ä»¥çåºgetActionMasked = getAction & MotionEvent.ACTION_MASK
èMotionEvent.ACTION_MASK æ¯ä¸ä¸ªå¸¸éå¼ï¼å¼ä¸º0xffï¼æ以getActionMaskedæ¹æ³åªä¿çäºä½8ä½çä¿¡æ¯ï¼ä¹å°±æ¯è¯´åªä¿çäºè§¦æ¸çå¨ä½ä¿¡æ¯ã
为ä»ä¹ç第ä¸æ¹æºç æ¶ï¼ææ¶åågetActionï¼ææ¶åågetActionMaskedå¢ï¼ä»ä¸é¢çåæä¸å¯ä»¥çåºæ¥ä¸ªæ以ç¶ï¼
getAction表示触æ¸å¨ä½çåå§ä½ä¿¡æ¯ï¼å½æ²¡æå¤ç¹è§¦æ§æ¶ï¼é«8ä½å³ä¸º0ï¼è¿ä¸ªæ¶ågetAction == getActionMaskedãæ以å½æ们确å®æ们èªå®ä¹çViewä¸ä¼ä½¿ç¨å°å¤ç¹è§¦æ§æ¶ï¼å°±å¯ä»¥ç´æ¥ä½¿ç¨getActionæ¥è¡¨ç¤ºå ·ä½ç触æ¸å¨ä½ãä½å¦æéè¦ä½¿ç¨å¤ç¹è§¦æ§ï¼æè æ¯ä¸ç¡®å®åé¢ä¼ä¸ä¼ä½¿ç¨å¤ç¹è§¦æ§ï¼å使ç¨getActionMaskedåæ¯æä¿é©çæä½ï¼æ以æ们ç»å¸¸çå°ä¸é¢è¿ä¸¤ç§åæ³ï¼
Androidä¸æ¯æ¯æå¤ç¹è§¦æ§çï¼é£ä¹å¨é«8ä½ä¸æ¯å¦ä½åå¨å¤ç¹è§¦æ§çç´¢å¼ä¿¡æ¯çå¢ï¼ä¸¾ä¸ªä¾åæ¥è¯´ï¼
å¦æä»getActionæ¹æ³ä¸è¿åçå¼æ¯0xï¼å表示æ¯ç¬¬ä¸ä¸ªè§¦æ§ç¹çACTION_DOWNæä½ãé«8ä½æ¯0表示第ä¸ä¸ªè§¦æ§ç¹ï¼ä½8ä½æ¯0表示ACTION_DOWNæä½ã
åçï¼å¦æè¿åå¼æ¯0xï¼å表示第äºä¸ªè§¦æ§ç¹çACTION_DOWNæä½ã
ä¹å°±æ¯è¯´ï¼getActionè¿åå¼çä½8ä½è¡¨ç¤ºè§¦æ¸å¨ä½çç±»åä¿¡æ¯ï¼èé«8ä½è¡¨ç¤ºè§¦æ§ç¹çç´¢å¼ä¿¡æ¯ï¼ä¹å°±æ¯åªä¸ä¸ªè§¦æ§ç¹çäºä»¶ã
Android Touch事件InputManagerService源码解析(二)
解析Android Touch事件分发过程,触摸触控深入InputManagerService源码。源码触摸事件的代码产生与传递机制是本文探讨的核心。
InputDispatcher接收到事件,触摸触控通过enqueueInboundEventLocked接口将事件放入mInboundQueue队列,源码等待分发处理。代码push源码
InputDispatcher内部线程在有事件时被唤醒,触摸触控执行dispatchOnce,源码根据事件类型调用dispatchMotionLocked进行处理。代码处理流程涉及找到要处理事件的触摸触控窗口。
窗口查找通过findFocusedWindowTargetsLocked方法实现,源码该方法从map中获取focusedWindowHandle和focusedApplicationHandle,代码存储目标窗口信息。触摸触控
这些句柄的源码初始化在Activity的生命周期回调中,如Activity.onResume时。代码具体路径涉及ActivityTaskManagerService、DisplayContent、买卖潮指标源码InputMonitor和InputManagerService。
分发循环由prepareDispatchCycleLocked、enqueueDispatchEntryLocked和enqueueDispatchEntriesLocked方法实现,最后调用startDispatchCycleLocked,将事件发送给对应进程。
InputReader持续从底层读取事件,InputDispatcher通过线程处理分发,直至事件被发送至目标进程。本文深入解析了Touch事件的分发机制与关键步骤,提供了对Android触摸事件处理过程的全面理解。
UE4-Slate源码学习(四)FSceneViewport
即视口是引擎中显示游戏画面的SWidget控件,也是编辑器中显示游戏内容的窗口。场景绘制视口(FSceneViewport)与SViewport绑定,用于场景渲染。鼠标捕获模式(EMouseCaptureMode)与鼠标锁定模式(EMouseLockMode)在项目设置中可配置,影响鼠标的2023新款源码交互。FSceneViewport事件处理包括鼠标按下(OnMouseButtonDown)、触摸开始(OnTouchStarted),事件响应后构造FReply,并更新几何体缓存、鼠标位置缓存。鼠标位置由绝对坐标转换为相对于视口的相对坐标。根据捕获状态和输入处理逻辑,事件最终被传递至PlayerController,通过PlayerInput管理。对于触摸输入,处理流程类似,调用InputTouch接口。
移动事件(OnMouseMove)、触摸移动(OnTouchMoved)记录鼠标的Delta和NumMouseSample累计值,Tick时处理。ProcessAccumulatedPointerInput在Tick阶段调用,洗地毯游戏源码处理键盘、鼠标输入,相关流程见第二章。完成输入处理后,FEngineLoop调用FinishedInputThisFrame,最终在ProcessAccumulatedPointerInput中调用InputAxis,处理至PlayerController的InputAxis,存储在PlayerInput中。其他事件如鼠标释放(OnMouseButtonUp)、触摸结束(OnTouchEnded)同样遵循类似流程。
若SWidget为视口,执行相关事件调用至ViewportClient接口,进而触发输入系统(PlayerController、PlayerInput、InputComponent)。日常游戏开发中,高山线源码通过视口事件实现如旋转相机、隐藏鼠标等操作。PlayerController提供三种模式(FInputModeUIOnly、FInputModeGameAndUI、FInputModeGameOnly),通过调整SViewport和ViewportClient参数,实现不同模式下的捕获、锁定、显隐鼠标功能。所讨论内容基于UE4版本4..2。
android onTouchEventåsetOnTouchListenerä¸onTouchçåºå«
触æ¸äºä»¶ååæºå¶ï¼å¥½å¥½ççï¼
/blog/
Androidä¸çäºä»¶å为æé®äºä»¶å触æ¸äºä»¶ï¼è¿é对触æ¸äºä»¶è¿è¡éè¿°ãTouchäºä»¶æ¯ç±ä¸ä¸ªACTION_DOWNï¼n个
ACTION_MOVEï¼ä¸ä¸ªACTION_UPç»æonClickï¼onLongClickï¼onScrollçäºä»¶ãAndroidä¸çæ§ä»¶é½æ¯ç»§æ¿
Viewè¿ä¸ªåºç±»çï¼èæ§ä»¶å为两ç§ï¼ä¸ç§æ¯ç»§æ¿Viewä¸è½å å«å ¶ä»æ§ä»¶çæ§ä»¶ï¼ä¸ç§æ¯ç»§æ¿ViewGroupå¯ä»¥å å«å ¶ä»æ§ä»¶çæ§ä»¶ï¼æä¸ç§°ä¸ºå®¹å¨æ§
件ï¼æ¯å¦ListViewï¼GridViewï¼LinearLayoutçã
è¿éå 对å 个å½æ°è®²è§£ä¸ã
Ø public boolean dispatchTouchEvent (MotionEventev) è¿ä¸ªæ¹æ³ååTouchEvent
Ø public booleanonInterceptTouchEvent(MotionEvent ev) è¿ä¸ªæ¹æ³æ¦æªTouchEvent
Ø public boolean onTouchEvent(MotionEvent ev) è¿ä¸ªæ¹æ³å¤çTouchEvent
å ¶ä¸viewç±»ä¸ædispatchTouchEventåonTouchEvent两个æ¹æ³ï¼ViewGroup继æ¿Viewï¼èä¸è¿æ°æ·»äºä¸ä¸ª
onInterceptTouchEventæ¹æ³ãActivityä¸ä¹æ onInterceptTouchEventæ¹æ³ï¼ä½æå¦å¤ä¸¤ç§æ¹æ³ãæ们å¯ä»¥
åç°ä¸é¢3个æ¹æ³é½æ¯è¿åbooleanï¼é£å代表ä»ä¹ææå¢ï¼
public boolean dispatchTouchEvent (MotionEvent ev)
Activityä¸è§£éï¼
Called to process touch screen
events.You can override this to intercept all touch screen events before
they aredispatched to the window. Be sure to call this implementation
for touch screenevents that should be handled normally.
Parameters
ev
The touch screen event.
Returns
· boolean Return true if this event was consumed.
å®ä¼è¢«è°ç¨å¤ç触æ¸å±äºä»¶ï¼å¯ä»¥éåè¦çæ¤æ¹æ³æ¥æ¦æªææ触æ¸å±äºä»¶å¨è¿äºäºä»¶ååå°çªå£ä¹åãé常åºè¯¥å¤ç触æ¸å±äºä»¶ï¼ä¸å®è¦è°ç¨è¿ä¸ªå®ç°ãå½è¿
åå¼ä¸ºtrueæ¶ï¼è¡¨ç¤ºè¿ä¸ªäºä»¶å·²ç»è¢«æ¶è´¹äºãä¾å¦å¨TextActivityä¸dispatchTouchEventå¨ACTION_MOVEè¿å
trueï¼è¿è¡ç»æå¦ä¸ï¼
ä¹å°±æ¯å®å¹¶æ²¡ææé£ACTION_MOVEååä¸å»ã
public boolean onInterceptTouchEvent (MotionEvent ev)
Implementthis
method to intercept all touch screen motion events. This allows you
towatch events as they are dispatched to your children, and take
ownership of thecurrent gesture at any point.
Usingthis function takes some care, as it has a fairly complicated interaction with View.onTouchEvent(MotionEvent),and
using it requires implementing that method as well as this one in
thecorrect way. Events will be received in the following order:
1. You will receive the down event here.
2. The
down event will be handled either by a child of this viewgroup, or
given to your own onTouchEvent() method to handle; this means youshould
implement onTouchEvent() to return true, so you will continue to see
therest of the gesture (instead of looking for a parent view to handle
it). Also,by returning true from onTouchEvent(), you will not receive
any followingevents in onInterceptTouchEvent() and all touch processing
must happen inonTouchEvent() like normal.
3. For
as long as you return false from this function, eachfollowing event (up
to and including the final up) will be delivered first hereand then to
the target's onTouchEvent().
4. If
you return true from here, you will not receive any followingevents:
the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to youronTouchEvent() method and no longer appear here.
Parameters
ev
The motion event being dispatched down the hierarchy.
Returns
· Return
true to steal motionevents from the children and have them dispatched
to this ViewGroup throughonTouchEvent(). The current target will receive
an ACTION_CANCEL event, and nofurther messages will be delivered here.
åºæ¬ææå°±æ¯ï¼
1. ACTION_DOWNé¦å ä¼ä¼ éå°onInterceptTouchEvent()æ¹æ³
2.å¦æ该ViewGroupçonInterceptTouchEvent()å¨æ¥æ¶å°downäºä»¶å¤çå®æä¹åreturn falseï¼é£ä¹åç»çmove, upçäºä»¶å°ç»§ç»ä¼å ä¼ éç»è¯¥ViewGroupï¼ä¹åæådownäºä»¶ä¸æ ·ä¼ éç»æç»çç®æ viewçonTouchEvent()å¤çã
3.å¦æ该ViewGroupçonInterceptTouchEvent()å¨æ¥æ¶å°downäºä»¶å¤çå®æä¹åreturn trueï¼é£ä¹åç»çmove, upçäºä»¶å°ä¸åä¼ éç»onInterceptTouchEvent()ï¼èæ¯ådownäºä»¶ä¸æ ·ä¼ éç»è¯¥ViewGroupçonTouchEvent()å¤çï¼æ³¨æï¼ç®æ viewå°æ¥æ¶ä¸å°ä»»ä½äºä»¶ã
4.å¦ææç»éè¦å¤çäºä»¶çviewçonTouchEvent()è¿åäºfalseï¼é£ä¹è¯¥äºä»¶å°è¢«ä¼ éè³å ¶ä¸ä¸å±æ¬¡çviewçonTouchEvent()å¤çã
5.å¦ææç»éè¦å¤çäºä»¶çviewçonTouchEvent()è¿åäºtrueï¼é£ä¹åç»äºä»¶å°å¯ä»¥ç»§ç»ä¼ éç»è¯¥viewçonTouchEvent()å¤çã
Android touchäºä»¶ä¼ éæºå¶ï¼
æ们å¯ä»¥ççandroidæºä»£ç ï¼
Activity.javaä¸
æä¸ä¸ç®¡onUserInteractionæ¹æ³å 为å®åªæ¯ä¸ä¸ªç©ºæ¹æ³å¦æä½ æ²¡å®ç°çè¯ãgetWindow().superDispatchTouchEvent(ev)ãå ¶ä¸getWindow()è¿åçæ¯PhoneWindowã
PhoneWindow.java:
æ¤å½æ°è°ç¨super.dispatchTouchEvent(event),Activityçrootviewæ¯
PhoneWindow.DecorView,å®ç»§æ¿FrameLayoutãéè¿super.dispatchTouchEventætouchäºä»¶æ´¾
åç»å个Activityçæ¯åviewãåæ¶æå¯ä»¥çå°ï¼å¦æåviewæ¦æªäºäºä»¶ï¼åä¸ä¼æ§è¡onTouchEventå½æ°ã
ViewGroup.javaä¸dispatchTouchEventæ¹æ³ï¼
ç±äºä»£ç è¿é¿è¿éå°±ä¸è´´åºæ¥äºï¼ä½ä¹ç¥éå®è¿åçæ¯
return target.dispatchTouchEvent(ev);
è¿étargetæçæ¯æååçç®æ ï¼å¯ä»¥æ¯å®æ¬èº«ï¼ä¹å¯ä»¥æ¯å®çåViewã
ViewGroup.javaä¸çonInterceptTouchEventæ¹æ³ï¼
é»è®¤æ åµä¸è¿åfalseãå³ä¸æ¦æªtouchäºä»¶ã
View.javaä¸çdispatchTouchEventæ¹æ³
è¿éæ们å¾æ¸ æ¥å¯ä»¥ç¥éå¦æifæ¡ä»¶ä¸æç«ådispatchTouchEventçè¿åå¼æ¯onTouchEventçè¿åå¼
View.javaä¸çonTouchEventæ¹æ³
linux内核hid触摸源码hid-multitouch.c剖析
在Linux内核中,hid-multitouch.c文件负责实现通用的HID触摸驱动。驱动结构定义在mt_driver中,通过module_hdi_driver()函数构建模块。mt_devices数组定义了设备参数,遵循USB-HID协议,通过HID_DEVICE宏对各个字段赋值。
mt_probe()函数执行初始化和配置多点触摸设备的操作,根据设备特性设置属性,启动硬件,并创建sysfs属性组。hid_parse()函数调用hid_open_report()解析HID报告,通过遍历数据并调用特定函数解析。hid_hw_start()函数启动底层HID硬件,而hid_connect()函数则实现连接功能。
对于需要通过USB接入触摸面板且满足HID协议的场景,可以使用hid-multitouch.c。接上两块触摸面板后,内核生成对应的设备节点链接。验证结果显示,内核能够正常解析触摸面板的数据,触摸事件上报亦正常。
UE4-Slate源码学习(二)slate事件触发
在探讨UE4-Slate源码学习中,首先进入概念理解阶段,虚拟触摸的开启会将鼠标左键操作转化为OnTouchStarted事件,使得编辑器下通过鼠标也能触发UI的触摸相关事件。实现这一功能的关键在于
FSlateApplication类中两个方法:IsFakingTouchEvents()用于判断是否开启虚拟触摸,SetGameIsFakingTouchEvents()用于设置虚拟触摸状态。
在平台调用Slate时,根据不同事件类型创建FPointerEvent对象,作为事件处理的载体,其包含触发事件的按键信息、鼠标位置、索引、是否为触摸事件等数据,用于后续事件的精确处理。
Slate用户类FSlateUser包含了索引、鼠标位置、聚焦对象、捕获状态和WidgetPath等信息,通过实例化多个FSlateUser对象,程序可以追踪多个用户输入,例如在多人游戏场景中,能够精准识别当前谁触发了A键。
聚焦和捕获功能分别通过Widget的聚焦和捕获机制实现,当聚焦后,事件将被相应Widget接收,并触发一系列聚焦相关的事件,如OnFocusReceived、OnFocusChanging、OnFocusLost等。以按钮点击为例,点击按钮触发OnMouseDown事件,若按钮被捕获,则移动到按钮外松开鼠标仍会触发按钮的OnMouseUp事件。
在处理输入事件时,会涉及多种策略,如FArrangedWidget、FArrangedChildren和FWidgetPath等,用于确定事件处理的路径和流程。FEventRouter类根据输入事件和用户输入策略(FDirectPolicy、FToLeafmostPolicy、FTunnelPolicy、FBubblePolicy)来组织和分发事件。
处理鼠标和触摸输入的流程分为OnMouseDown和OnTouchStarted,通过Route函数根据策略处理事件,实现事件的触发和响应。移动事件则通过OnMouseMove和OnTouchMoved处理,根据输入类型和用户状态执行相应操作。拖拽事件OnDragDetected则在拖拽开始时触发,允许开发者自定义拖拽行为和数据传递。
最终,事件处理完成后,将调用相关函数清理记录,包括更新用户位置和路径,以及触发OnMouseUp或OnTouchEnded等事件。
UE4-Slate源码的学习涵盖了事件触发、用户输入处理、事件路由策略等多个方面,理解这些机制和流程对于深入掌握Slate框架至关重要。源码版本4..2提供了丰富的功能和细节,为开发者提供了一套强大且灵活的UI管理解决方案。