diff options
3 files changed, 153 insertions, 107 deletions
diff --git a/services/core/java/com/android/server/wm/DragInputEventReceiver.java b/services/core/java/com/android/server/wm/DragInputEventReceiver.java new file mode 100644 index 000000000000..b4bbc9055631 --- /dev/null +++ b/services/core/java/com/android/server/wm/DragInputEventReceiver.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import static android.view.InputDevice.SOURCE_CLASS_POINTER; +import static android.view.MotionEvent.ACTION_CANCEL; +import static android.view.MotionEvent.ACTION_DOWN; +import static android.view.MotionEvent.ACTION_MOVE; +import static android.view.MotionEvent.ACTION_UP; +import static android.view.MotionEvent.BUTTON_STYLUS_PRIMARY; +import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG; +import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; + +import android.os.Looper; +import android.util.Slog; +import android.view.InputChannel; +import android.view.InputDevice; +import android.view.InputEvent; +import android.view.InputEventReceiver; +import android.view.MotionEvent; + +/** + * Input receiver for drag and drop + */ +class DragInputEventReceiver extends InputEventReceiver { + private final WindowManagerService mService; + private final DragDropController mDragDropController; + + // Set, if stylus button was down at the start of the drag. + private boolean mStylusButtonDownAtStart; + // Indicates the first event to check for button state. + private boolean mIsStartEvent = true; + // Set to true to ignore input events after the drag gesture is complete but the drag events + // are still being dispatched. + private boolean mMuteInput = false; + + public DragInputEventReceiver(InputChannel inputChannel, Looper looper, + DragDropController controller, WindowManagerService service) { + super(inputChannel, looper); + mDragDropController = controller; + mService = service; + } + + @Override + public void onInputEvent(InputEvent event, int displayId) { + boolean handled = false; + try { + synchronized (mService.mWindowMap) { + if (!mDragDropController.dragDropActiveLocked()) { + // The drag has ended but the clean-up message has not been processed by + // window manager. Drop events that occur after this until window manager + // has a chance to clean-up the input handle. + handled = true; + return; + } + if (!(event instanceof MotionEvent) + || (event.getSource() & SOURCE_CLASS_POINTER) == 0 + || mMuteInput) { + return; + } + final MotionEvent motionEvent = (MotionEvent) event; + boolean endDrag = false; + final float newX = motionEvent.getRawX(); + final float newY = motionEvent.getRawY(); + final boolean isStylusButtonDown = + (motionEvent.getButtonState() & BUTTON_STYLUS_PRIMARY) != 0; + + if (mIsStartEvent) { + if (isStylusButtonDown) { + // First event and the button was down, check for the button being + // lifted in the future, if that happens we'll drop the item. + mStylusButtonDownAtStart = true; + } + mIsStartEvent = false; + } + + switch (motionEvent.getAction()) { + case ACTION_DOWN: { + if (DEBUG_DRAG) Slog.w(TAG_WM, "Unexpected ACTION_DOWN in drag layer"); + } + break; + + case ACTION_MOVE: { + if (mStylusButtonDownAtStart && !isStylusButtonDown) { + if (DEBUG_DRAG) { + Slog.d(TAG_WM, "Button no longer pressed; dropping at " + + newX + "," + newY); + } + mMuteInput = true; + endDrag = mDragDropController.mDragState + .notifyDropLocked(newX, newY); + } else { + // move the surface and tell the involved window(s) where we are + mDragDropController.mDragState.notifyMoveLocked(newX, newY); + } + } + break; + + case ACTION_UP: { + if (DEBUG_DRAG) { + Slog.d(TAG_WM, "Got UP on move channel; dropping at " + + newX + "," + newY); + } + mMuteInput = true; + endDrag = mDragDropController.mDragState + .notifyDropLocked(newX, newY); + } + break; + + case ACTION_CANCEL: { + if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!"); + mMuteInput = true; + endDrag = true; + } + break; + } + + if (endDrag) { + if (DEBUG_DRAG) + Slog.d(TAG_WM, "Drag ended; tearing down state"); + // tell all the windows that the drag has ended + // endDragLocked will post back to looper to dispose the receiver + // since we still need the receiver for the last finishInputEvent. + mDragDropController.mDragState.endDragLocked(); + mStylusButtonDownAtStart = false; + mIsStartEvent = true; + } + + handled = true; + } + } catch (Exception e) { + Slog.e(TAG_WM, "Exception caught by drag handleMotion", e); + } finally { + finishInputEvent(event, handled); + } + } +} diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index ba956bde9ed0..9a955de9706c 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -57,7 +57,6 @@ import android.view.animation.Interpolator; import com.android.internal.view.IDragAndDropPermissions; import com.android.server.input.InputApplicationHandle; import com.android.server.input.InputWindowHandle; -import com.android.server.wm.WindowManagerService.DragInputEventReceiver; import java.util.ArrayList; @@ -151,8 +150,8 @@ class DragState { mServerChannel = channels[0]; mClientChannel = channels[1]; mService.mInputManager.registerInputChannel(mServerChannel, null); - mInputEventReceiver = mService.new DragInputEventReceiver(mClientChannel, - mService.mH.getLooper()); + mInputEventReceiver = new DragInputEventReceiver(mClientChannel, + mService.mH.getLooper(), mDragDropController, mService); mDragApplicationHandle = new InputApplicationHandle(null); mDragApplicationHandle.name = "drag"; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index af26345da153..2ee1541426e3 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -771,110 +771,6 @@ public class WindowManagerService extends IWindowManager.Stub private WindowContentFrameStats mTempWindowRenderStats; - final class DragInputEventReceiver extends InputEventReceiver { - // Set, if stylus button was down at the start of the drag. - private boolean mStylusButtonDownAtStart; - // Indicates the first event to check for button state. - private boolean mIsStartEvent = true; - // Set to true to ignore input events after the drag gesture is complete but the drag events - // are still being dispatched. - private boolean mMuteInput = false; - - public DragInputEventReceiver(InputChannel inputChannel, Looper looper) { - super(inputChannel, looper); - } - - @Override - public void onInputEvent(InputEvent event, int displayId) { - boolean handled = false; - try { - if (mDragDropController.mDragState == null) { - // The drag has ended but the clean-up message has not been processed by - // window manager. Drop events that occur after this until window manager - // has a chance to clean-up the input handle. - handled = true; - return; - } - if (event instanceof MotionEvent - && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 - && !mMuteInput) { - final MotionEvent motionEvent = (MotionEvent)event; - boolean endDrag = false; - final float newX = motionEvent.getRawX(); - final float newY = motionEvent.getRawY(); - final boolean isStylusButtonDown = - (motionEvent.getButtonState() & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0; - - if (mIsStartEvent) { - if (isStylusButtonDown) { - // First event and the button was down, check for the button being - // lifted in the future, if that happens we'll drop the item. - mStylusButtonDownAtStart = true; - } - mIsStartEvent = false; - } - - switch (motionEvent.getAction()) { - case MotionEvent.ACTION_DOWN: { - if (DEBUG_DRAG) { - Slog.w(TAG_WM, "Unexpected ACTION_DOWN in drag layer"); - } - } break; - - case MotionEvent.ACTION_MOVE: { - if (mStylusButtonDownAtStart && !isStylusButtonDown) { - if (DEBUG_DRAG) Slog.d(TAG_WM, "Button no longer pressed; dropping at " - + newX + "," + newY); - mMuteInput = true; - synchronized (mWindowMap) { - endDrag = mDragDropController.mDragState.notifyDropLocked(newX, newY); - } - } else { - synchronized (mWindowMap) { - // move the surface and tell the involved window(s) where we are - mDragDropController.mDragState.notifyMoveLocked(newX, newY); - } - } - } break; - - case MotionEvent.ACTION_UP: { - if (DEBUG_DRAG) Slog.d(TAG_WM, "Got UP on move channel; dropping at " - + newX + "," + newY); - mMuteInput = true; - synchronized (mWindowMap) { - endDrag = mDragDropController.mDragState.notifyDropLocked(newX, newY); - } - } break; - - case MotionEvent.ACTION_CANCEL: { - if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag cancelled!"); - mMuteInput = true; - endDrag = true; - } break; - } - - if (endDrag) { - if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state"); - // tell all the windows that the drag has ended - synchronized (mWindowMap) { - // endDragLocked will post back to looper to dispose the receiver - // since we still need the receiver for the last finishInputEvent. - mDragDropController.mDragState.endDragLocked(); - } - mStylusButtonDownAtStart = false; - mIsStartEvent = true; - } - - handled = true; - } - } catch (Exception e) { - Slog.e(TAG_WM, "Exception caught by drag handleMotion", e); - } finally { - finishInputEvent(event, handled); - } - } - } - /** * Whether the UI is currently running in touch mode (not showing * navigational focus because the user is directly pressing the screen). |