记不住密码怎么办?
http://a.app.qq.com/o/simple.jsp?pkgname=com.wa505.kf.epassword
一个是InputReader,一个是InputDispatcher。方法是dispatchTouch。
入口点是InputReader 的loopOnce方法.
InputReader里面有个线程叫做InputReaderThread,threadLoop
[code="java"]InputReaderThread::InputReaderThread(const sp& reader) :
Thread(/*canCallJava*/ true), mReader(reader) {
}
InputReaderThread::~InputReaderThread() {
}
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputDispatcher::dispatchOnce() { nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout(); nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay(); nsecs_t nextWakeupTime = LONG_LONG_MAX; { // acquire lock AutoMutex _l(mLock); dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime); if (runCommandsLockedInterruptible()) { nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately } } // release lock // Wait for callback or timeout or wake. (make sure we round up, not down) nsecs_t currentTime = now(); int32_t timeoutMillis; if (nextWakeupTime > currentTime) { uint64_t timeout = uint64_t(nextWakeupTime - currentTime); timeout = (timeout + 999999LL) / 1000000LL; timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout); } else { timeoutMillis = 0; } mLooper->pollOnce(timeoutMillis); }
case EventEntry::TYPE_MOTION: { MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent); if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) { dropReason = DROP_REASON_APP_SWITCH; } done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime); break;
bool InputDispatcher::dispatchMotionLocked( nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) { // Preprocessing. if (! entry->dispatchInProgress) { entry->dispatchInProgress = true; resetTargetsLocked(); logOutboundMotionDetailsLocked("dispatchMotion - ", entry); } // Clean up if dropping the event. if (*dropReason != DROP_REASON_NOT_DROPPED) { resetTargetsLocked(); setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED); return true; } bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER; // Identify targets. if (! mCurrentInputTargetsValid) { int32_t injectionResult; if (isPointerEvent) { // Pointer event. (eg. touchscreen) injectionResult = findTouchedWindowTargetsLocked(currentTime, entry, nextWakeupTime); } else { // Non touch event. (eg. trackball) injectionResult = findFocusedWindowTargetsLocked(currentTime, entry, nextWakeupTime); } if (injectionResult == INPUT_EVENT_INJECTION_PENDING) { return false; } setInjectionResultLocked(entry, injectionResult); if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) { return true; } addMonitoringTargetsLocked(); commitTargetsLocked(); } // Dispatch the motion. dispatchEventToCurrentInputTargetsLocked(currentTime, entry, false); return true; }
startDispatchCycleLocked 中的方法 status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId, motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState, xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision, motionEntry->downTime, firstMotionSample->eventTime, motionEntry->pointerCount, motionEntry->pointerIds, firstMotionSample->pointerCoords);
ViewRoot有个InputHandler
private final InputHandler mInputHandler = new InputHandler() { public void handleKey(KeyEvent event, Runnable finishedCallback) { startInputEvent(finishedCallback); dispatchKey(event, true); } public void handleMotion(MotionEvent event, Runnable finishedCallback) { startInputEvent(finishedCallback); dispatchMotion(event, true); } };
InputHandler注册给了系统
InputQueue.registerInputChannel(mInputChannel, mInputHandler, Looper.myQueue());
dispatchMotion(event, true);方法如下 private void dispatchMotion(MotionEvent event, boolean sendDone) { int source = event.getSource(); if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { dispatchPointer(event, sendDone); } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) { dispatchTrackball(event, sendDone); } else { // TODO Log.v(TAG, "Dropping unsupported motion event (unimplemented): " + event); if (sendDone) { finishInputEvent(); } } }
调用了dispatchPointer
ViewRoot本身就是Handler直接sendMessageAtTime
然后就进入了View的焦点系统。
下面就说一下Activity的焦点是怎么回事。
InputDisapatcher.cpp中调用了如下方法 dispatchEventToCurrentInputTargetsLocked(currentTime, motionEntry, true /*resumeWithAppendedMotionSample*/);
然后
dispatchEventToCurrentInputTargetsLocked
调用了如下方法
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry, nsecs_t* nextWakeupTime) { mCurrentInputTargets.clear(); int32_t injectionResult; // If there is no currently focused window and no focused application // then drop the event. if (! mFocusedWindow) { if (mFocusedApplication) { #if DEBUG_FOCUS LOGD("Waiting because there is no focused window but there is a " "focused application that may eventually add a window: %s.", getApplicationWindowLabelLocked(mFocusedApplication, NULL).string()); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, mFocusedApplication, NULL, nextWakeupTime); goto Unresponsive; } LOGI("Dropping event because there is no focused window or focused application."); injectionResult = INPUT_EVENT_INJECTION_FAILED; goto Failed; } // Check permissions. if (! checkInjectionPermission(mFocusedWindow, entry->injectionState)) { injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED; goto Failed; } // If the currently focused window is paused then keep waiting. if (mFocusedWindow->paused) { #if DEBUG_FOCUS LOGD("Waiting because focused window is paused."); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, mFocusedApplication, mFocusedWindow, nextWakeupTime); goto Unresponsive; } // If the currently focused window is still working on previous events then keep waiting. if (! isWindowFinishedWithPreviousInputLocked(mFocusedWindow)) { #if DEBUG_FOCUS LOGD("Waiting because focused window still processing previous input."); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, mFocusedApplication, mFocusedWindow, nextWakeupTime); goto Unresponsive; } // Success! Output targets. injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED; addWindowTargetLocked(mFocusedWindow, InputTarget::FLAG_FOREGROUND, BitSet32(0)); // Done. Failed: Unresponsive: nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime); updateDispatchStatisticsLocked(currentTime, entry, injectionResult, timeSpentWaitingForApplication); #if DEBUG_FOCUS LOGD("findFocusedWindow finished: injectionResult=%d, " "timeSpendWaitingForApplication=%0.1fms", injectionResult, timeSpentWaitingForApplication / 1000000.0); #endif return injectionResult; }
move事件的处理和Down事件的处理很不相同。
新建立的Window在处理焦点的时候,按下事件没有起来之前,保持了原来的焦点窗口。除非ACTION_UP事件收到以后
/* Updates the cached window information provided to the input dispatcher. */ public void updateInputWindowsLw() { // Populate the input window list with information about all of the windows that // could potentially receive input. // As an optimization, we could try to prune the list of windows but this turns // out to be difficult because only the native code knows for sure which window // currently has touch focus. final ArrayList<WindowState> windows = mWindows; final int N = windows.size(); for (int i = N - 1; i >= 0; i--) { final WindowState child = windows.get(i); if (child.mInputChannel == null || child.mRemoved) { // Skip this window because it cannot possibly receive input. continue; } final int flags = child.mAttrs.flags; final int type = child.mAttrs.type; final boolean hasFocus = (child == mInputFocus); final boolean isVisible = child.isVisibleLw(); final boolean hasWallpaper = (child == mWallpaperTarget) && (type != WindowManager.LayoutParams.TYPE_KEYGUARD); // Add a window to our list of input windows. final InputWindow inputWindow = mTempInputWindows.add(); inputWindow.inputChannel = child.mInputChannel; inputWindow.name = child.toString(); inputWindow.layoutParamsFlags = flags; inputWindow.layoutParamsType = type; inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos(); inputWindow.visible = isVisible; inputWindow.canReceiveKeys = child.canReceiveKeys(); inputWindow.hasFocus = hasFocus; inputWindow.hasWallpaper = hasWallpaper; inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false; inputWindow.layer = child.mLayer; inputWindow.ownerPid = child.mSession.mPid; inputWindow.ownerUid = child.mSession.mUid; final Rect frame = child.mFrame; inputWindow.frameLeft = frame.left; inputWindow.frameTop = frame.top; inputWindow.frameRight = frame.right; inputWindow.frameBottom = frame.bottom; final Rect visibleFrame = child.mVisibleFrame; inputWindow.visibleFrameLeft = visibleFrame.left; inputWindow.visibleFrameTop = visibleFrame.top; inputWindow.visibleFrameRight = visibleFrame.right; inputWindow.visibleFrameBottom = visibleFrame.bottom; switch (child.mTouchableInsets) { default: case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME: inputWindow.touchableAreaLeft = frame.left; inputWindow.touchableAreaTop = frame.top; inputWindow.touchableAreaRight = frame.right; inputWindow.touchableAreaBottom = frame.bottom; break; case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: { Rect inset = child.mGivenContentInsets; inputWindow.touchableAreaLeft = frame.left + inset.left; inputWindow.touchableAreaTop = frame.top + inset.top; inputWindow.touchableAreaRight = frame.right - inset.right; inputWindow.touchableAreaBottom = frame.bottom - inset.bottom; break; } case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: { Rect inset = child.mGivenVisibleInsets; inputWindow.touchableAreaLeft = frame.left + inset.left; inputWindow.touchableAreaTop = frame.top + inset.top; inputWindow.touchableAreaRight = frame.right - inset.right; inputWindow.touchableAreaBottom = frame.bottom - inset.bottom; break; } } } // Send windows to native code. mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray()); // Clear the list in preparation for the next round. // Also avoids keeping InputChannel objects referenced unnecessarily. mTempInputWindows.clear(); }
真正的Input的控制是通过以下方式
/**
* Z-ordered (bottom-most first) list of all Window objects.
*/
final ArrayList<WindowState> mWindows = new ArrayList<WindowState>();
/** * Z-ordered (bottom-most first) list of all Window objects. */ final ArrayList<WindowState> mWindows = new ArrayList<WindowState>();
另外的touch的target并不是通过input focus 获得的。而是通过visible来获得
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry, nsecs_t* nextWakeupTime) { enum InjectionPermission { INJECTION_PERMISSION_UNKNOWN, INJECTION_PERMISSION_GRANTED, INJECTION_PERMISSION_DENIED }; mCurrentInputTargets.clear(); nsecs_t startTime = now(); // For security reasons, we defer updating the touch state until we are sure that // event injection will be allowed. // // FIXME In the original code, screenWasOff could never be set to true. // The reason is that the POLICY_FLAG_WOKE_HERE // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was // actually enqueued using the policyFlags that appeared in the final EV_SYN // events upon which no preprocessing took place. So policyFlags was always 0. // In the new native input dispatcher we're a bit more careful about event // preprocessing so the touches we receive can actually have non-zero policyFlags. // Unfortunately we obtain undesirable behavior. // // Here's what happens: // // When the device dims in anticipation of going to sleep, touches // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause // the device to brighten and reset the user activity timer. // Touches on other windows (such as the launcher window) // are dropped. Then after a moment, the device goes to sleep. Oops. // // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE // instead of POLICY_FLAG_WOKE_HERE... // bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE; int32_t action = entry->action; int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK; // Update the touch state as needed based on the properties of the touch event. int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING; InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN; if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { mTempTouchState.reset(); mTempTouchState.down = true; } else { mTempTouchState.copyFrom(mTouchState); } bool isSplit = mTempTouchState.split && mTempTouchState.down; if (maskedAction == AMOTION_EVENT_ACTION_DOWN || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) { /* Case 1: New splittable pointer going down. */ int32_t pointerIndex = getMotionEventActionPointerIndex(action); int32_t x = int32_t(entry->firstSample.pointerCoords[pointerIndex].x); int32_t y = int32_t(entry->firstSample.pointerCoords[pointerIndex].y); const InputWindow* newTouchedWindow = NULL; const InputWindow* topErrorWindow = NULL; // Traverse windows from front to back to find touched window and outside targets. size_t numWindows = mWindows.size(); for (size_t i = 0; i < numWindows; i++) { const InputWindow* window = & mWindows.editItemAt(i); int32_t flags = window->layoutParamsFlags; if (flags & InputWindow::FLAG_SYSTEM_ERROR) { if (! topErrorWindow) { topErrorWindow = window; } } if (window->visible) { if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) { bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0; if (isTouchModal || window->touchableAreaContainsPoint(x, y)) { if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) { newTouchedWindow = window; } break; // found touched window, exit window loop } } if (maskedAction == AMOTION_EVENT_ACTION_DOWN && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) { int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE; if (isWindowObscuredAtPointLocked(window, x, y)) { outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; } mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0)); } } } // If there is an error window but it is not taking focus (typically because // it is invisible) then wait for it. Any other focused window may in // fact be in ANR state. if (topErrorWindow && newTouchedWindow != topErrorWindow) { #if DEBUG_FOCUS LOGD("Waiting because system error window is pending."); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, NULL, NULL, nextWakeupTime); injectionPermission = INJECTION_PERMISSION_UNKNOWN; goto Unresponsive; } // Figure out whether splitting will be allowed for this window. if (newTouchedWindow && (newTouchedWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH)) { // New window supports splitting. isSplit = true; } else if (isSplit) { // New window does not support splitting but we have already split events. // Assign the pointer to the first foreground window we find. // (May be NULL which is why we put this code block before the next check.) newTouchedWindow = mTempTouchState.getFirstForegroundWindow(); } // If we did not find a touched window then fail. if (! newTouchedWindow) { if (mFocusedApplication) { #if DEBUG_FOCUS LOGD("Waiting because there is no touched window but there is a " "focused application that may eventually add a new window: %s.", getApplicationWindowLabelLocked(mFocusedApplication, NULL).string()); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, mFocusedApplication, NULL, nextWakeupTime); goto Unresponsive; } LOGI("Dropping event because there is no touched window or focused application."); injectionResult = INPUT_EVENT_INJECTION_FAILED; goto Failed; } // Set target flags. int32_t targetFlags = InputTarget::FLAG_FOREGROUND; if (isSplit) { targetFlags |= InputTarget::FLAG_SPLIT; } if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) { targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; } // Update the temporary touch state. BitSet32 pointerIds; if (isSplit) { uint32_t pointerId = entry->pointerIds[pointerIndex]; pointerIds.markBit(pointerId); } mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds); } else { /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */ // If the pointer is not currently down, then ignore the event. if (! mTempTouchState.down) { LOGI("Dropping event because the pointer is not down."); injectionResult = INPUT_EVENT_INJECTION_FAILED; goto Failed; } } // Check permission to inject into all touched foreground windows and ensure there // is at least one touched foreground window. { bool haveForegroundWindow = false; for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { const TouchedWindow& touchedWindow = mTempTouchState.windows[i]; if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) { haveForegroundWindow = true; if (! checkInjectionPermission(touchedWindow.window, entry->injectionState)) { injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED; injectionPermission = INJECTION_PERMISSION_DENIED; goto Failed; } } } if (! haveForegroundWindow) { #if DEBUG_INPUT_DISPATCHER_POLICY LOGD("Dropping event because there is no touched foreground window to receive it."); #endif injectionResult = INPUT_EVENT_INJECTION_FAILED; goto Failed; } // Permission granted to injection into all touched foreground windows. injectionPermission = INJECTION_PERMISSION_GRANTED; } // Ensure all touched foreground windows are ready for new input. for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { const TouchedWindow& touchedWindow = mTempTouchState.windows[i]; if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) { // If the touched window is paused then keep waiting. if (touchedWindow.window->paused) { #if DEBUG_INPUT_DISPATCHER_POLICY LOGD("Waiting because touched window is paused."); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, NULL, touchedWindow.window, nextWakeupTime); goto Unresponsive; } // If the touched window is still working on previous events then keep waiting. if (! isWindowFinishedWithPreviousInputLocked(touchedWindow.window)) { #if DEBUG_FOCUS LOGD("Waiting because touched window still processing previous input."); #endif injectionResult = handleTargetsNotReadyLocked(currentTime, entry, NULL, touchedWindow.window, nextWakeupTime); goto Unresponsive; } } } // If this is the first pointer going down and the touched window has a wallpaper // then also add the touched wallpaper windows so they are locked in for the duration // of the touch gesture. if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { const InputWindow* foregroundWindow = mTempTouchState.getFirstForegroundWindow(); if (foregroundWindow->hasWallpaper) { for (size_t i = 0; i < mWindows.size(); i++) { const InputWindow* window = & mWindows[i]; if (window->layoutParamsType == InputWindow::TYPE_WALLPAPER) { mTempTouchState.addOrUpdateWindow(window, InputTarget::FLAG_WINDOW_IS_OBSCURED, BitSet32(0)); } } } } // Success! Output targets. injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED; for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i); addWindowTargetLocked(touchedWindow.window, touchedWindow.targetFlags, touchedWindow.pointerIds); } // Drop the outside touch window since we will not care about them in the next iteration. mTempTouchState.removeOutsideTouchWindows(); Failed: // Check injection permission once and for all. if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) { if (checkInjectionPermission(NULL, entry->injectionState)) { injectionPermission = INJECTION_PERMISSION_GRANTED; } else { injectionPermission = INJECTION_PERMISSION_DENIED; } } // Update final pieces of touch state if the injector had permission. if (injectionPermission == INJECTION_PERMISSION_GRANTED) { if (maskedAction == AMOTION_EVENT_ACTION_UP || maskedAction == AMOTION_EVENT_ACTION_CANCEL) { // All pointers up or canceled. mTempTouchState.reset(); } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) { // First pointer went down. if (mTouchState.down) { #if DEBUG_FOCUS LOGD("Pointer down received while already down."); #endif } } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) { // One pointer went up. if (isSplit) { int32_t pointerIndex = getMotionEventActionPointerIndex(action); uint32_t pointerId = entry->pointerIds[pointerIndex]; for (size_t i = 0; i < mTempTouchState.windows.size(); ) { TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i); if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) { touchedWindow.pointerIds.clearBit(pointerId); if (touchedWindow.pointerIds.isEmpty()) { mTempTouchState.windows.removeAt(i); continue; } } i += 1; } } } // Save changes to touch state. mTouchState.copyFrom(mTempTouchState); } else { #if DEBUG_FOCUS LOGD("Not updating touch focus because injection was denied."); #endif } Unresponsive: // Reset temporary touch state to ensure we release unnecessary references to input channels. mTempTouchState.reset(); nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime); updateDispatchStatisticsLocked(currentTime, entry, injectionResult, timeSpentWaitingForApplication); #if DEBUG_FOCUS LOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, " "timeSpentWaitingForApplication=%0.1fms", injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0); #endif return injectionResult; }
最关键的几行代码,说明了Windows是如何找到触屏的输入焦点的:
if (window->visible) { if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) { bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0; if (isTouchModal || window->touchableAreaContainsPoint(x, y)) { if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) { newTouchedWindow = window; } break; // found touched window, exit window loop } } if (maskedAction == AMOTION_EVENT_ACTION_DOWN && (flags & InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)) { int32_t outsideTargetFlags = InputTarget::FLAG_OUTSIDE; if (isWindowObscuredAtPointLocked(window, x, y)) { outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED; } mTempTouchState.addOrUpdateWindow(window, outsideTargetFlags, BitSet32(0)); } }
// Focus tracking for touch.
struct TouchedWindow {
const InputWindow* window;
int32_t targetFlags;
BitSet32 pointerIds;
sp<InputChannel> channel;
};
struct TouchState {
bool down;
bool split;
Vector<TouchedWindow> windows;
TouchState();
~TouchState();
void reset();
void copyFrom(const TouchState& other);
void addOrUpdateWindow(const InputWindow* window, int32_t targetFlags, BitSet32 pointerIds);
void removeOutsideTouchWindows();
const InputWindow* getFirstForegroundWindow();
};
另外如何定义按键和其他触屏焦点的:
/* Updates the cached window information provided to the input dispatcher. */
public void updateInputWindowsLw() {
// Populate the input window list with information about all of the windows that
// could potentially receive input.
// As an optimization, we could try to prune the list of windows but this turns
// out to be difficult because only the native code knows for sure which window
// currently has touch focus.
final ArrayList<WindowState> windows = mWindows;
final int N = windows.size();
for (int i = N - 1; i >= 0; i--) {
final WindowState child = windows.get(i);
if (child.mInputChannel == null || child.mRemoved) {
// Skip this window because it cannot possibly receive input.
continue;
}
final int flags = child.mAttrs.flags;
final int type = child.mAttrs.type;
final boolean hasFocus = (child == mInputFocus);
//本行代码确定,一次性的focusWindow只有一个。
final boolean isVisible = child.isVisibleLw();
final boolean hasWallpaper = (child == mWallpaperTarget)
&& (type != WindowManager.LayoutParams.TYPE_KEYGUARD);
记不住密码怎么办?
http://a.app.qq.com/o/simple.jsp?pkgname=com.wa505.kf.epassword
相关推荐
在Android开发中,触摸事件(TouchEvent)是用户与设备交互的主要方式之一,它涉及到Activity、View及ViewGroup之间的事件分发。理解Android TouchEvent事件传递机制对于构建具有良好用户体验的应用至关重要。本文将...
本文将深入解析Android TouchEvent的工作流程,帮助开发者更好地理解和利用这一关键功能。 Android系统通过MotionEvent类来封装触摸事件的信息,包括按下、移动和释放等操作。MotionEvent提供了丰富的API,如`get...
`TouchEvent`是Android系统处理这些交互的核心机制。本文将深入探讨Android触摸事件的工作原理、监听器的使用以及如何在应用程序中有效地处理触摸事件。 一、触摸事件的生命周期 Android触摸事件遵循一个称为...
最后,为了更好地调试和理解触摸事件的流程,可以利用Log输出各个阶段的事件状态,这对于理解Android的事件处理机制非常有帮助。 总结起来,`android touchevent`涉及到的主要知识点包括:触摸事件的三个基本动作,...
在Android系统中,TouchEvent事件处理是用户界面交互的核心部分,它涉及到UI组件的触摸响应,是应用程序接收并处理用户触摸屏幕动作的主要方式。本篇将深入解析Android的TouchEvent事件传递机制,帮助开发者更好地...
OffsetAnimator OffsetAnimator lets animate objects basing on touchevents, so users can be engaged in an animation process. Usage Add the library to your project: Add it in your root build.gradle at ...
首先,`MotionEvent`是Android系统用于表示触摸事件的数据类,它包含了与触摸屏幕相关的各种信息,如动作类型(ACTION_DOWN、ACTION_UP等)、坐标位置等。当用户在屏幕上进行触控操作时,系统会生成一系列的`...
TouchEvent的dispatchTouchEvent事件分发流程图
Qt是一个跨平台的应用程序开发框架,支持多种操作系统,包括Android。它提供了丰富的功能,使开发者能够在移动设备上创建用户界面,而QGestureEvent是Qt中处理触摸输入的关键组件。 **Qt for Android** Qt for ...
其次,CEGUI与Android的输入系统集成也是个挑战。Android使用事件驱动的输入处理机制,而CEGUI则有自己的事件模型。开发者需要编写适配器,将Android的MotionEvent、TouchEvent等转换为CEGUI可识别的事件。 然后,...
游戏事件(如触摸事件)会被监听并触发相应的反应,这可能涉及到Android的View类和TouchEvent。此外,游戏的状态管理,如暂停、恢复、结束等,也会有对应的函数来处理。 资源管理是游戏开发中的重要部分,会说话的...
它的作用是提供一种系统性的方法,以有效地应对挑战、优化流程或实现目标。以下是方案的主要作用: 问题解决: 方案的核心目标是解决问题。通过系统性的规划和执行,方案能够分析问题的根本原因,提供可行的解决...
Android提供了TouchEvent机制来处理用户的输入,你需要适配ACTION_DOWN、ACTION_MOVE和ACTION_UP等事件。 6. **游戏状态管理**:游戏有开始、暂停、结束等状态,需要合理地管理这些状态。例如,使用布尔变量跟踪...
* 触摸事件:在Android系统中,需要使用TouchEvent来处理用户的触摸事件。 * 键盘操作:在Android系统中,需要使用KeyListener来处理用户的键盘事件。 4. 进展编码 * 登录:需要实现用户的登录功能,能够登录到...
在本主题中,我们将深入探讨一个基于Android操作系统开发的飞机游戏,其核心编程语言为Java。这个项目展示了如何使用Java和Android SDK来构建一个互动性强、用户体验良好的移动游戏。让我们一起解析这个Android飞机...
在Android系统中,开发者通常使用Java或Kotlin语言进行编程,构建这样的应用会涉及到以下几个关键知识点: 1. **用户界面(UI)设计**:应用的界面设计是吸引用户的关键。开发者会使用Android Studio提供的布局工具...
本书不仅涵盖了Android框架的基础概念,还详细介绍了其内部架构、组件间通信机制、系统服务、应用生命周期管理、UI绘制流程、输入事件处理、多媒体支持、网络通信、性能优化等多个方面,是Android开发者不可多得的...
《Android源码开发实战6.12》是针对Android系统深度开发的一份宝贵资源,它涵盖了从基础到高级的各种主题,旨在帮助开发者更好地理解和利用Android的底层机制。在这个压缩包中,主要包含的是第六章第十二节的内容。...
通过这个项目,开发者可以深入理解Android系统的输入机制,提升布局设计和动画编程的能力,同时也能学习到如何在实际应用中兼顾用户体验和安全性。对于Android开发初学者来说,这是一个很好的实践项目,有助于提升...
5. **触摸事件处理**:Android通过TouchEvent系统提供对用户触摸输入的处理。在贪吃蛇游戏中,我们需要监听用户的滑动操作来改变蛇的方向。 6. **动画**:Android提供了多种动画API,如ValueAnimator和...