基于Android T代码分析: 在freeform窗口的标题栏拖动时移动窗口流程和拖动freeform窗口边沿改变大小流程
在线看Android源代码网址:
http://aospxref.com/android-13.0.0_r3
https://cs.android.com
概要:DecorCaptionView、TaskPositioningController、TaskPositioner、
SystemGesturesPointerEventListener、TaskTapPointerEventListener
拖动移动窗口和拖动改变大小
1,计算出窗口拖动时的窗口边界:mWindowDragBounds
2,通过resizeTask()方法把新的窗口边界mWindowDragBounds更新给Task
3,Task通过SurfaceControl控制调整surface的大小和位置,通知给SurfaceFlinger进行更新
DecorCaptionView.java
@Override
public boolean onTouch(View v, MotionEvent e) {
case MotionEvent.ACTION_MOVE:
if (!mDragging && mCheckForDragging && (fromMouse || passedSlop(x, y))) {
mCheckForDragging = false;
mDragging = true;
startMovingTask(e.getRawX(), e.getRawY());
}
break;
return mDragging || mCheckForDragging;
}
->
View.java
public final boolean startMovingTask(float startX, float startY) {
if (ViewDebug.DEBUG_POSITIONING) {
Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
}
try {
return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
} catch (RemoteException e) {
Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
}
return false;
}
public void finishMovingTask() {
if (ViewDebug.DEBUG_POSITIONING) {
Log.d(VIEW_LOG_TAG, "finishMovingTask");
}
try {
mAttachInfo.mSession.finishMovingTask(mAttachInfo.mWindow);
} catch (RemoteException e) {
Log.e(VIEW_LOG_TAG, "Unable to finish moving", e);
}
}
->
WindowManagerService.java
mTaskPositioningController = new TaskPositioningController(this);
Session.java
@Override
public boolean startMovingTask(IWindow window, float startX, float startY) {
if (DEBUG_TASK_POSITIONING) Slog.d(
TAG_WM, "startMovingTask: {" + startX + "," + startY + "}");
final long ident = Binder.clearCallingIdentity();
try {
return mService.mTaskPositioningController.startMovingTask(window, startX, startY);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override
public void finishMovingTask(IWindow window) {
if (DEBUG_TASK_POSITIONING) Slog.d(TAG_WM, "finishMovingTask");
final long ident = Binder.clearCallingIdentity();
try {
mService.mTaskPositioningController.finishTaskPositioning(window);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
TaskPositioningController.java
boolean startMovingTask(IWindow window, float startX, float startY) {
WindowState win = null;
synchronized (mService.mGlobalLock) {
win = mService.windowForClientLocked(null, window, false);
if (!startPositioningLocked(
win, false , false , startX, startY)) {
return false;
}
mService.mAtmService.setFocusedTask(win.getTask().mTaskId);
}
return true;
}
拖动freeform窗口边沿改变大小流程
TaskTapPointerEventListener.java
public void onPointerEvent(MotionEvent motionEvent) {
case MotionEvent.ACTION_DOWN: {
if (!mTouchExcludeRegion.contains(x, y)) {
mService.mTaskPositioningController.handleTapOutsideTask(
mDisplayContent, x, y);
}
}
break;
}
->
void handleTapOutsideTask(DisplayContent displayContent, int x, int y) {
mService.mH.post(() -> {
synchronized (mService.mGlobalLock) {
final Task task = displayContent.findTaskForResizePoint(x, y);
if (task != null) {
if (!task.isResizeable()) {
return;
}
if (!startPositioningLocked(task.getTopVisibleAppMainWindow(), true ,
task.preserveOrientationOnResize(), x, y)) {
return;
}
mService.mAtmService.setFocusedTask(task.mTaskId);
}
}
});
}
private boolean startPositioningLocked(WindowState win, boolean resize,
boolean preserveOrientation, float startX, float startY) {
if (DEBUG_TASK_POSITIONING)
Slog.d(TAG_WM, "startPositioningLocked: "
+ "win=" + win + ", resize=" + resize + ", preserveOrientation="
+ preserveOrientation + ", {" + startX + ", " + startY + "}");
if (win == null || win.mActivityRecord == null) {
Slog.w(TAG_WM, "startPositioningLocked: Bad window " + win);
return false;
}
if (win.mInputChannel == null) {
Slog.wtf(TAG_WM, "startPositioningLocked: " + win + " has no input channel, "
+ " probably being removed");
return false;
}
final DisplayContent displayContent = win.getDisplayContent();
if (displayContent == null) {
Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
return false;
}
mPositioningDisplay = displayContent;
mTaskPositioner = TaskPositioner.create(mService);
mTaskPositioner.register(displayContent, win);
WindowState transferFocusFromWin = win;
if (displayContent.mCurrentFocus != null && displayContent.mCurrentFocus != win
&& displayContent.mCurrentFocus.mActivityRecord == win.mActivityRecord) {
transferFocusFromWin = displayContent.mCurrentFocus;
}
if (!mService.mInputManager.transferTouchFocus(
transferFocusFromWin.mInputChannel, mTaskPositioner.mClientChannel,
false )) {
Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
cleanUpTaskPositioner();
return false;
}
mTaskPositioner.startDrag(resize, preserveOrientation, startX, startY);
return true;
}
public void finishTaskPositioning(IWindow window) {
if (mTaskPositioner != null && mTaskPositioner.mClientCallback == window.asBinder()) {
finishTaskPositioning();
}
}
->
TaskPositioner.java
1,计算出窗口拖动时的窗口边界:mWindowDragBounds
void startDrag(boolean resize, boolean preserveOrientation, float startX, float startY) {
notifyMoveLocked(startX, startY);
}
->
notifyMoveLocked()
->
resizeDrag(x, y);
updateDraggedBounds(Rect newBounds) {
mWindowDragBounds.set(newBounds);
}
2,通过resizeTask()方法把新的窗口边界mWindowDragBounds更新给Task
private boolean onInputEvent(InputEvent event) {
if (!(event instanceof MotionEvent)
|| (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
return false;
}
final MotionEvent motionEvent = (MotionEvent) event;
if (mDragEnded) {
return true;
}
final float newX = motionEvent.getRawX();
final float newY = motionEvent.getRawY();
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_DOWN @ {" + newX + ", " + newY + "}");
}
}
break;
case MotionEvent.ACTION_MOVE: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_MOVE @ {" + newX + ", " + newY + "}");
}
synchronized (mService.mGlobalLock) {
mDragEnded = notifyMoveLocked(newX, newY);
mTask.getDimBounds(mTmpRect);
}
if (!mTmpRect.equals(mWindowDragBounds)) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
"wm.TaskPositioner.resizeTask");
mService.mAtmService.resizeTask(
mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
}
break;
case MotionEvent.ACTION_UP: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_UP @ {" + newX + ", " + newY + "}");
}
mDragEnded = true;
}
break;
case MotionEvent.ACTION_CANCEL: {
if (DEBUG_TASK_POSITIONING) {
Slog.w(TAG, "ACTION_CANCEL @ {" + newX + ", " + newY + "}");
}
mDragEnded = true;
}
break;
}
if (mDragEnded) {
final boolean wasResizing = mResizing;
synchronized (mService.mGlobalLock) {
endDragLocked();
mTask.getDimBounds(mTmpRect);
}
if (wasResizing && !mTmpRect.equals(mWindowDragBounds)) {
mService.mAtmService.resizeTask(
mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
}
mService.mTaskPositioningController.finishTaskPositioning();
}
return true;
}
->
ActivityTaskManagerService.java
public boolean resizeTask(int taskId, Rect bounds, int resizeMode) {
return task.resize(bounds, resizeMode, preserveWindow);
}
->
Task.java
void resize(Rect displayedBounds, boolean preserveWindows, boolean deferResume) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "task.resize_" + getRootTaskId());
mAtmService.deferWindowLayout();
try {
final PooledConsumer c = PooledLambda.obtainConsumer(
Task::processTaskResizeBounds, PooledLambda.__(Task.class),
displayedBounds);
forAllTasks(c, true );
c.recycle();
if (!deferResume) {
ensureVisibleActivitiesConfiguration(topRunningActivity(), preserveWindows);
}
} finally {
mAtmService.continueWindowLayout();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
->
private static void processTaskResizeBounds(Task task, Rect displayedBounds) {
if (!task.isResizeable()) return;
task.setBounds(displayedBounds);
}
->
private int setBounds(Rect existing, Rect bounds) {
if (equivalentBounds(existing, bounds)) {
return BOUNDS_CHANGE_NONE;
}
final int result = super.setBounds(!inMultiWindowMode() ? null : bounds);
updateSurfaceBounds();
return result;
}
->
private void updateSurfaceBounds() {
updateSurfaceSize(getSyncTransaction());
updateSurfacePositionNonOrganized();
scheduleAnimation();
}
void updateSurfaceSize(SurfaceControl.Transaction transaction) {
if (mSurfaceControl == null || isOrganized()) {
return;
}
int width = 0;
int height = 0;
if (isRootTask()) {
final Rect taskBounds = getBounds();
width = taskBounds.width();
height = taskBounds.height();
}
if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
return;
}
transaction.setWindowCrop(mSurfaceControl, width, height);
mLastSurfaceSize.set(width, height);
}
void updateSurfacePosition(Transaction t) {
if (mSurfaceControl == null || mSurfaceAnimator.hasLeash() || mSurfaceFreezer.hasLeash()) {
return;
}
getRelativePosition(mTmpPos);
final int deltaRotation = getRelativeDisplayRotation();
if (mTmpPos.equals(mLastSurfacePosition) && deltaRotation == mLastDeltaRotation) {
return;
}
t.setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
if (mTransitionController.isShellTransitionsEnabled()
&& !mTransitionController.useShellTransitionsRotation()) {
if (deltaRotation != Surface.ROTATION_0) {
updateSurfaceRotation(t, deltaRotation, null );
} else if (deltaRotation != mLastDeltaRotation) {
t.setMatrix(mSurfaceControl, 1, 0, 0, 1);
}
}
mLastDeltaRotation = deltaRotation;
}
SurfaceControl.java
Transaction
public Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
checkPreconditions(sc);
if (crop != null) {
nativeSetWindowCrop(mNativeObject, sc.mNativeObject,
crop.left, crop.top, crop.right, crop.bottom);
} else {
nativeSetWindowCrop(mNativeObject, sc.mNativeObject, 0, 0, 0, 0);
}
return this;
}
public Transaction setPosition(@NonNull SurfaceControl sc, float x, float y) {
checkPreconditions(sc);
nativeSetPosition(mNativeObject, sc.mNativeObject, x, y);
return this;
}
WindowState.java
freeform自由形式工作区上窗口边界外的窗口大小调整手柄的厚度,以捕获该区域中的触摸事件。
static final int RESIZE_HANDLE_WIDTH_IN_DP = 30;
DisplayContent.java
private Region mTouchExcludeRegion = new Region();