在打开多窗口的时候,比如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)的传送多么的不容易,那么多的操作,多次加工,千辛万苦才传给了接收者。这一路,太辛苦。