diff options
6 files changed, 143 insertions, 21 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index ede377de0b14..5c639330831b 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -567,10 +567,10 @@ class DisplayContent { return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mStacks; } - TaskStack getDockedStack() { + TaskStack getDockedStackLocked() { for (int i = mStacks.size() - 1; i >= 0; i--) { TaskStack stack = mStacks.get(i); - if (stack.mStackId == DOCKED_STACK_ID) { + if (stack.mStackId == DOCKED_STACK_ID && stack.isVisibleLocked()) { return stack; } } diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index ad207d4b8939..8c5d319439ba 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.ActivityManager.DOCKED_STACK_ID; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; @@ -23,11 +24,19 @@ import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; import static android.view.WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING; import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; +import static com.android.server.wm.TaskStack.DOCKED_BOTTOM; +import static com.android.server.wm.TaskStack.DOCKED_INVALID; +import static com.android.server.wm.TaskStack.DOCKED_LEFT; +import static com.android.server.wm.TaskStack.DOCKED_RIGHT; +import static com.android.server.wm.TaskStack.DOCKED_TOP; import android.content.Context; import android.graphics.PixelFormat; import android.graphics.Rect; +import android.os.RemoteException; +import android.util.Slog; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; @@ -35,13 +44,20 @@ import android.view.WindowManagerGlobal; /** * Controls showing and hiding of a docked stack divider on the display. */ -public class DockedStackDividerController { +public class DockedStackDividerController implements View.OnTouchListener { private static final String TAG = "DockedStackDivider"; private final Context mContext; private final int mDividerWidth; private final DisplayContent mDisplayContent; private View mView; private Rect mTmpRect = new Rect(); + private Rect mLastResizeRect = new Rect(); + private int mStartX; + private int mStartY; + private TaskStack mTaskStack; + private Rect mOriginalRect = new Rect(); + private int mDockSide; + DockedStackDividerController(Context context, DisplayContent displayContent) { mContext = context; @@ -53,6 +69,7 @@ public class DockedStackDividerController { private void addDivider() { View view = LayoutInflater.from(mContext).inflate( com.android.internal.R.layout.docked_stack_divider, null); + view.setOnTouchListener(this); WindowManagerGlobal manager = WindowManagerGlobal.getInstance(); WindowManager.LayoutParams params = new WindowManager.LayoutParams( mDividerWidth, MATCH_PARENT, TYPE_DOCK_DIVIDER, @@ -65,6 +82,7 @@ public class DockedStackDividerController { } private void removeDivider() { + mView.setOnTouchListener(null); WindowManagerGlobal manager = WindowManagerGlobal.getInstance(); manager.removeView(mView, true /* immediate */); mView = null; @@ -75,7 +93,7 @@ public class DockedStackDividerController { } void update() { - TaskStack stack = mDisplayContent.getDockedStack(); + TaskStack stack = mDisplayContent.getDockedStackLocked(); if (stack != null && mView == null) { addDivider(); } else if (stack == null && mView != null) { @@ -87,9 +105,8 @@ public class DockedStackDividerController { return mDividerWidth; } - void positionDockedStackedDivider(Rect frame) { - TaskStack stack = mDisplayContent.getDockedStack(); + TaskStack stack = mDisplayContent.getDockedStackLocked(); if (stack == null) { // Unfortunately we might end up with still having a divider, even though the underlying // stack was already removed. This is because we are on AM thread and the removal of the @@ -99,19 +116,84 @@ public class DockedStackDividerController { final @TaskStack.DockSide int side = stack.getDockSide(); stack.getBounds(mTmpRect); switch (side) { - case TaskStack.DOCKED_LEFT: + case DOCKED_LEFT: frame.set(mTmpRect.right, frame.top, mTmpRect.right + frame.width(), frame.bottom); break; - case TaskStack.DOCKED_TOP: + case DOCKED_TOP: frame.set(frame.left, mTmpRect.bottom, mTmpRect.right, mTmpRect.bottom + frame.height()); break; - case TaskStack.DOCKED_RIGHT: + case DOCKED_RIGHT: frame.set(mTmpRect.left - frame.width(), frame.top, mTmpRect.left, frame.bottom); break; - case TaskStack.DOCKED_BOTTOM: + case DOCKED_BOTTOM: frame.set(frame.left, mTmpRect.top - frame.height(), frame.right, mTmpRect.top); break; } } + + @Override + public boolean onTouch(View v, MotionEvent event) { + final int action = event.getAction() & MotionEvent.ACTION_MASK; + switch (action) { + case MotionEvent.ACTION_DOWN: + // We use raw values, because getX/Y() would give us results relative to the + // dock divider bounds. + mStartX = (int) event.getRawX(); + mStartY = (int) event.getRawY(); + synchronized (mDisplayContent.mService.mWindowMap) { + mTaskStack = mDisplayContent.getDockedStackLocked(); + mTaskStack.getBounds(mOriginalRect); + mDockSide = mTaskStack.getDockSide(); + } + break; + case MotionEvent.ACTION_MOVE: + if (mTaskStack != null) { + resizeStack(event); + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mTaskStack = null; + mDockSide = TaskStack.DOCKED_INVALID; + break; + } + return true; + } + + private void resizeStack(MotionEvent event) { + mTmpRect.set(mOriginalRect); + final int deltaX = (int) event.getRawX() - mStartX; + final int deltaY = (int) event.getRawY() - mStartY; + switch (mDockSide) { + case DOCKED_LEFT: + mTmpRect.right += deltaX; + break; + case DOCKED_TOP: + mTmpRect.bottom += deltaY; + break; + case DOCKED_RIGHT: + mTmpRect.left += deltaX; + break; + case DOCKED_BOTTOM: + mTmpRect.top += deltaY; + break; + } + if (mTmpRect.equals(mLastResizeRect)) { + return; + } + mLastResizeRect.set(mTmpRect); + try { + mDisplayContent.mService.mActivityManager.resizeStack(DOCKED_STACK_ID, mTmpRect); + } catch (RemoteException e) { + } + } + + boolean isResizing() { + return mTaskStack != null; + } + + int getWidthAdjustment() { + return getWidth() / 2; + } } diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 4244205aabf8..6c391ade60cc 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH; import android.app.ActivityManagerNative; import android.graphics.Rect; @@ -170,7 +171,7 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { private void addInputWindowHandleLw(final InputWindowHandle inputWindowHandle, final WindowState child, int flags, final int type, final boolean isVisible, - final boolean hasFocus, final boolean hasWallpaper) { + final boolean hasFocus, final boolean hasWallpaper, DisplayContent displayContent) { // Add a window to our list of input windows. inputWindowHandle.name = child.toString(); final boolean modal = (flags & (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL @@ -202,6 +203,20 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { inputWindowHandle.frameTop = frame.top; inputWindowHandle.frameRight = frame.right; inputWindowHandle.frameBottom = frame.bottom; + if (child.mAttrs.type == TYPE_DOCK_DIVIDER) { + // We need to determine if the divider is horizontal or vertical and adjust its handle + // frame accordingly. + int adjustment = displayContent.mDividerControllerLocked.getWidthAdjustment(); + if (inputWindowHandle.frameRight - inputWindowHandle.frameLeft > + inputWindowHandle.frameTop - inputWindowHandle.frameBottom) { + // Horizontal divider. + inputWindowHandle.frameTop -= adjustment; + inputWindowHandle.frameBottom += adjustment; + } else { + inputWindowHandle.frameLeft -= adjustment; + inputWindowHandle.frameRight += adjustment; + } + } if (child.mGlobalScale != 1) { // If we are scaling the window, input coordinates need @@ -277,7 +292,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { final int numDisplays = mService.mDisplayContents.size(); final WallpaperController wallpaperController = mService.mWallpaperControllerLocked; for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - WindowList windows = mService.mDisplayContents.valueAt(displayNdx).getWindowList(); + final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx); + final WindowList windows = displayContent.getWindowList(); for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { final WindowState child = windows.get(winNdx); final InputChannel inputChannel = child.mInputChannel; @@ -315,7 +331,7 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { } addInputWindowHandleLw(inputWindowHandle, child, flags, type, isVisible, hasFocus, - hasWallpaper); + hasWallpaper, displayContent); } } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 96fcf93b5981..1d9126d06189 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -86,6 +86,7 @@ public class TaskStack implements DimLayer.DimLayerUser { static final int DOCKED_TOP = 2; static final int DOCKED_RIGHT = 3; static final int DOCKED_BOTTOM = 4; + @IntDef({ DOCKED_INVALID, DOCKED_LEFT, @@ -353,7 +354,7 @@ public class TaskStack implements DimLayer.DimLayerUser { bounds = new Rect(); displayContent.getLogicalDisplayRect(mTmpRect); getInitialDockedStackBounds(mTmpRect, bounds, mStackId, - mDisplayContent.mDividerControllerLocked.getWidth() / 2); + mDisplayContent.mDividerControllerLocked.getWidthAdjustment()); } updateDisplayInfo(bounds); @@ -566,4 +567,16 @@ public class TaskStack implements DimLayer.DimLayerUser { return DOCKED_INVALID; } } + + boolean isVisibleLocked() { + for (int i = mTasks.size() - 1; i >= 0; i--) { + Task task = mTasks.get(i); + for (int j = task.mAppTokens.size() - 1; j >= 0; j--) { + if (!task.mAppTokens.get(j).hidden) { + return true; + } + } + } + return false; + } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 22f9f50fe6dd..8126a4706ce2 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; +import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; @@ -1894,13 +1895,13 @@ public class WindowManagerService extends IWindowManager.Stub return res; } - if (outInputChannel != null && (attrs.inputFeatures - & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { + final boolean openInputChannels = (outInputChannel != null + && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0); + if (openInputChannels) { String name = win.makeInputChannelName(); InputChannel[] inputChannels = InputChannel.openInputChannelPair(name); win.setInputChannel(inputChannels[0]); inputChannels[1].transferTo(outInputChannel); - mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c73dbaf607eb..d49e3a761c51 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -34,6 +34,7 @@ import static com.android.server.wm.WindowManagerService.DEBUG_POWER; import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE; import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY; +import android.app.ActivityManager; import android.app.AppOpsManager; import android.os.PowerManager; import android.os.RemoteCallbackList; @@ -129,7 +130,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { boolean mAttachedHidden; // is our parent window hidden? boolean mWallpaperVisible; // for wallpaper, what was last vis report? boolean mDragResizing; - boolean mDragResizeChanging; RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks; @@ -1701,13 +1701,23 @@ final class WindowState implements WindowManagerPolicy.WindowState { } boolean isDragResizeChanged() { + return mDragResizing != computeDragResizing(); + } + + private boolean computeDragResizing() { final Task task = getTask(); - return task != null && mDragResizing != task.isDragResizing(); + if (task == null) { + return false; + } + if (task.isDragResizing()) { + return true; + } + return mDisplayContent.mDividerControllerLocked.isResizing() && + !task.inFreeformWorkspace() && !task.isFullscreen(); } void setDragResizing() { - final Task task = getTask(); - mDragResizing = task != null && task.isDragResizing(); + mDragResizing = computeDragResizing(); } boolean isDragResizing() { |