android2.3 监控鼠标滑动事件(2)

 

在上一篇中,当action == MotionEvent.ACTION_MOVE,设置自定义的action给自己的应用接受。

但别的应用也可能会处理MotionEvent.ACTION_MOVE事件,从而导致有别的问题出现。

所以,自定义一个action事件,MotionEvent.ACTION_HOVER_MOVE。

在InputReader.cpp中修改鼠标事件

InputReader.cpp

void MouseInputMapper::sync(nsecs_t when) {
    uint32_t fields = mAccumulator.fields;
    if (fields == 0) {
        return; // no new state changes, so nothing to do
    }

    int motionEventAction;
    PointerCoords pointerCoords;
    nsecs_t downTime;
    { // acquire lock
        AutoMutex _l(mLock);

       bool downChanged = fields & Accumulator::FIELD_BTN_MOUSE;
       if (downChanged) {
           if (mAccumulator.btnMouse) {
               mLocked.down = true;
               mLocked.downTime = when;
           } else {
               mLocked.down = false;
           }
           motionEventAction = mLocked.down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
        } else if (mLocked.down) {
            motionEventAction = AMOTION_EVENT_ACTION_MOVE;
        } else {
            motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
        }

	.....

 }

InputDispatcher.cpp中增加对hover_move事件的处理

void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
        uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
        uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
        float xPrecision, float yPrecision, nsecs_t downTime) {

	......


    bool needWake;
    { // acquire lock
        AutoMutex _l(mLock);

	if (action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
        	for (EventEntry* entry = mInboundQueue.tailSentinel.prev;
        	                    entry != & mInboundQueue.headSentinel; entry = entry->prev) {
			if (entry->type != EventEntry::TYPE_MOTION) {
				// Keep looking for motion events.
				continue;
			}

			MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
			if (motionEntry->deviceId != deviceId) {
				// Keep looking for this device.
				continue;
			}

			if (motionEntry->action != AMOTION_EVENT_ACTION_HOVER_MOVE
					|| motionEntry->pointerCount != pointerCount
					|| motionEntry->isInjected()) {
				// Last motion event in the queue for this device is not compatible for
				// appending new samples.  Stop here.
				goto NoBatchingOrStreaming2;
			}

			// The last motion event is a move and is compatible for appending.
			// Do the batching magic.
			mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
#if DEBUG_BATCHING
			LOGD("Appended motion sample onto batch for most recent "
					"hover motion event for this device in the inbound queue.");
#endif
			return; // done!

		}

        	if (mCurrentInputTargetsValid) {
			for (size_t i = 0; i < mCurrentInputTargets.size(); i++) {
				const InputTarget& inputTarget = mCurrentInputTargets[i];
				if ((inputTarget.flags & InputTarget::FLAG_FOREGROUND) == 0) {
					// Skip non-foreground targets.  We only want to stream if there is at
					// least one foreground target whose dispatch is still in progress.
					continue;
				}

				ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
				if (connectionIndex < 0) {
					// Connection must no longer be valid.
					continue;
				}

				sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
				if (connection->outboundQueue.isEmpty()) {
					// This foreground target has an empty outbound queue.
					continue;
				}

				DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
				if (! dispatchEntry->inProgress
						|| dispatchEntry->eventEntry->type != EventEntry::TYPE_MOTION
						|| dispatchEntry->isSplit()) {
					// No motion event is being dispatched, or it is being split across
					// windows in which case we cannot stream.
					continue;
				}

				MotionEntry* motionEntry = static_cast<MotionEntry*>(
						dispatchEntry->eventEntry);
				if (motionEntry->action != AMOTION_EVENT_ACTION_HOVER_MOVE
						|| motionEntry->deviceId != deviceId
						|| motionEntry->pointerCount != pointerCount
						|| motionEntry->isInjected()) {
					// The motion event is not compatible with this move.
					continue;
				}

				// Hurray!  This foreground target is currently dispatching a move event
				// that we can stream onto.  Append the motion sample and resume dispatch.
				mAllocator.appendMotionSample(motionEntry, eventTime, pointerCoords);
#if DEBUG_BATCHING
				LOGD("Appended motion sample onto batch for most recently dispatched "
						"hover motion event for this device in the outbound queues.  "
						"Attempting to stream the motion sample.");
#endif
				nsecs_t currentTime = now();
				dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry,
						true /*resumeWithAppendedMotionSample*/);

				runCommandsLockedInterruptible();
				return; // done!
			}
		}

NoBatchingOrStreaming2:;
        }

        // Attempt batching and streaming of move events.
        if (action == AMOTION_EVENT_ACTION_MOVE) {

		......

	}

    }

InputTransport.cpp

status_t InputPublisher::publishMotionEvent(

	....

    // Cache essential information about the motion event to ensure that a malicious consumer
    // cannot confuse the publisher by modifying the contents of the shared memory buffer while
    // it is being updated.
    if (action == AMOTION_EVENT_ACTION_MOVE || action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
        mMotionEventPointerCount = pointerCount;
        mMotionEventSampleDataStride = InputMessage::sampleDataStride(pointerCount);
        mMotionEventSampleDataTail = InputMessage::sampleDataPtrIncrement(
                mSharedMessage->motion.sampleData, mMotionEventSampleDataStride);
    } else {
        mMotionEventSampleDataTail = NULL;
    }
    return OK;

}

 

ViewRoot 中,修改不变。当ViewGroup分发事件时,在View中屏蔽自定义的action。

public boolean dispatchTouchEvent(MotionEvent event) {
        if (!onFilterTouchEventForSecurity(event)) {
            return false;
        }
        
        // Not handled the event, the subView will handle it.   
        if (event.getAction() == MotionEvent.ACTION_HOVER_MOVE) {
        	return true;
        }

        if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
                mOnTouchListener.onTouch(this, event)) {
            return true;
        }
        return onTouchEvent(event);
    }

这样,子View只能重写此方法,来得到我们的action。

public class UButton extends ImageView {

	private OnTouchListener mOnTouchListener;
	
	public UButton(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public void setOnTouchListener(OnTouchListener l) {
        	mOnTouchListener = l;
    	}
	
	public boolean dispatchTouchEvent(MotionEvent event) {
		if (!onFilterTouchEventForSecurity(event)) {
            return false;
        }
		
		if (mOnTouchListener != null && mOnTouchListener.onTouch(this, event)) {
            return true;
        }
        return super.onTouchEvent(event);
	}
}

 

消息获取流程附图
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值