blob: f7035c502cc26a15b15ea1b24b173da1ecb60284 [file] [log] [blame]
Chong Zhang8e89b312015-09-09 15:09:30 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Wale Ogunwale59a73ca2015-09-14 12:54:50 -070019import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
20import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
Chong Zhang87b21722015-09-21 15:39:51 -070021import static android.app.ActivityManager.RESIZE_MODE_USER;
Chong Zhang6de2ae82015-09-30 18:25:21 -070022import static android.app.ActivityManager.RESIZE_MODE_USER_FORCED;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080023import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
Wale Ogunwale228d4042015-09-13 10:17:34 -070024import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
Wale Ogunwalecad05a02015-09-25 10:41:44 -070025import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080026import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
27import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
28import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
29import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
30import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -070031import static com.android.server.wm.WindowManagerService.dipToPixel;
Wale Ogunwale231b06e2015-09-16 12:03:09 -070032import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
33import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
Chong Zhang8e89b312015-09-09 15:09:30 -070034
35import android.annotation.IntDef;
36import android.graphics.Point;
37import android.graphics.Rect;
38import android.os.Looper;
39import android.os.Process;
40import android.os.RemoteException;
Wale Ogunwalecad05a02015-09-25 10:41:44 -070041import android.os.Trace;
Chong Zhang8e89b312015-09-09 15:09:30 -070042import android.util.DisplayMetrics;
43import android.util.Slog;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080044import android.view.BatchedInputEventReceiver;
Wale Ogunwale4f52bc62015-09-24 13:47:31 -070045import android.view.Choreographer;
Chong Zhang8e89b312015-09-09 15:09:30 -070046import android.view.Display;
Wale Ogunwale228d4042015-09-13 10:17:34 -070047import android.view.DisplayInfo;
Chong Zhang8e89b312015-09-09 15:09:30 -070048import android.view.InputChannel;
49import android.view.InputDevice;
50import android.view.InputEvent;
Chong Zhang8e89b312015-09-09 15:09:30 -070051import android.view.MotionEvent;
Wale Ogunwale228d4042015-09-13 10:17:34 -070052import android.view.SurfaceControl;
Chong Zhang8e89b312015-09-09 15:09:30 -070053import android.view.WindowManager;
54
Wale Ogunwale228d4042015-09-13 10:17:34 -070055import com.android.server.input.InputApplicationHandle;
56import com.android.server.input.InputWindowHandle;
57import com.android.server.wm.WindowManagerService.H;
58
59import java.lang.annotation.Retention;
60import java.lang.annotation.RetentionPolicy;
61
62class TaskPositioner implements DimLayer.DimLayerUser {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080063 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskPositioner" : TAG_WM;
Chong Zhang8e89b312015-09-09 15:09:30 -070064
Wale Ogunwale228d4042015-09-13 10:17:34 -070065 // The margin the pointer position has to be within the side of the screen to be
66 // considered at the side of the screen.
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -070067 static final int SIDE_MARGIN_DIP = 100;
Wale Ogunwale228d4042015-09-13 10:17:34 -070068
Chong Zhang8e89b312015-09-09 15:09:30 -070069 @IntDef(flag = true,
70 value = {
71 CTRL_NONE,
72 CTRL_LEFT,
73 CTRL_RIGHT,
74 CTRL_TOP,
75 CTRL_BOTTOM
76 })
77 @Retention(RetentionPolicy.SOURCE)
78 @interface CtrlType {}
79
80 private static final int CTRL_NONE = 0x0;
81 private static final int CTRL_LEFT = 0x1;
82 private static final int CTRL_RIGHT = 0x2;
83 private static final int CTRL_TOP = 0x4;
84 private static final int CTRL_BOTTOM = 0x8;
85
Filip Gruszczynski64b6b442016-01-18 13:20:58 -080086 public static final float RESIZING_HINT_ALPHA = 0.5f;
87
88 public static final int RESIZING_HINT_DURATION_MS = 0;
89
Chong Zhang8e89b312015-09-09 15:09:30 -070090 private final WindowManagerService mService;
91 private WindowPositionerEventReceiver mInputEventReceiver;
92 private Display mDisplay;
93 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
Wale Ogunwale228d4042015-09-13 10:17:34 -070094 private DimLayer mDimLayer;
95 @CtrlType
96 private int mCurrentDimSide;
97 private Rect mTmpRect = new Rect();
98 private int mSideMargin;
Wale Ogunwaleb8051b82015-09-17 15:41:52 -070099 private int mMinVisibleWidth;
100 private int mMinVisibleHeight;
Chong Zhang8e89b312015-09-09 15:09:30 -0700101
Chong Zhang3005e752015-09-18 18:46:28 -0700102 private Task mTask;
Chong Zhang09b21ef2015-09-14 10:20:21 -0700103 private boolean mResizing;
Chong Zhang8e89b312015-09-09 15:09:30 -0700104 private final Rect mWindowOriginalBounds = new Rect();
105 private final Rect mWindowDragBounds = new Rect();
106 private float mStartDragX;
107 private float mStartDragY;
108 @CtrlType
109 private int mCtrlType = CTRL_NONE;
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700110 private boolean mDragEnded = false;
Chong Zhang8e89b312015-09-09 15:09:30 -0700111
112 InputChannel mServerChannel;
113 InputChannel mClientChannel;
114 InputApplicationHandle mDragApplicationHandle;
115 InputWindowHandle mDragWindowHandle;
116
Wale Ogunwale4f52bc62015-09-24 13:47:31 -0700117 private final class WindowPositionerEventReceiver extends BatchedInputEventReceiver {
118 public WindowPositionerEventReceiver(
119 InputChannel inputChannel, Looper looper, Choreographer choreographer) {
120 super(inputChannel, looper, choreographer);
Chong Zhang8e89b312015-09-09 15:09:30 -0700121 }
122
123 @Override
124 public void onInputEvent(InputEvent event) {
125 if (!(event instanceof MotionEvent)
126 || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
127 return;
128 }
129 final MotionEvent motionEvent = (MotionEvent) event;
130 boolean handled = false;
131
132 try {
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700133 if (mDragEnded) {
134 // The drag has ended but the clean-up message has not been processed by
135 // window manager. Drop events that occur after this until window manager
136 // has a chance to clean-up the input handle.
137 handled = true;
138 return;
139 }
140
Chong Zhang8e89b312015-09-09 15:09:30 -0700141 final float newX = motionEvent.getRawX();
142 final float newY = motionEvent.getRawY();
143
144 switch (motionEvent.getAction()) {
145 case MotionEvent.ACTION_DOWN: {
146 if (DEBUG_TASK_POSITIONING) {
147 Slog.w(TAG, "ACTION_DOWN @ {" + newX + ", " + newY + "}");
148 }
149 } break;
150
151 case MotionEvent.ACTION_MOVE: {
152 if (DEBUG_TASK_POSITIONING){
153 Slog.w(TAG, "ACTION_MOVE @ {" + newX + ", " + newY + "}");
154 }
155 synchronized (mService.mWindowMap) {
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700156 mDragEnded = notifyMoveLocked(newX, newY);
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800157 mTask.getDimBounds(mTmpRect);
Chong Zhang8e89b312015-09-09 15:09:30 -0700158 }
Wale Ogunwale04ad7b12015-10-02 12:43:27 -0700159 if (!mTmpRect.equals(mWindowDragBounds)) {
160 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
161 "wm.TaskPositioner.resizeTask");
162 try {
163 mService.mActivityManager.resizeTask(
164 mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
165 } catch (RemoteException e) {
166 }
167 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
168 }
Chong Zhang8e89b312015-09-09 15:09:30 -0700169 } break;
170
171 case MotionEvent.ACTION_UP: {
172 if (DEBUG_TASK_POSITIONING) {
173 Slog.w(TAG, "ACTION_UP @ {" + newX + ", " + newY + "}");
174 }
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700175 mDragEnded = true;
Chong Zhang8e89b312015-09-09 15:09:30 -0700176 } break;
177
178 case MotionEvent.ACTION_CANCEL: {
179 if (DEBUG_TASK_POSITIONING) {
180 Slog.w(TAG, "ACTION_CANCEL @ {" + newX + ", " + newY + "}");
181 }
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700182 mDragEnded = true;
Chong Zhang8e89b312015-09-09 15:09:30 -0700183 } break;
184 }
185
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700186 if (mDragEnded) {
Wale Ogunwale04ad7b12015-10-02 12:43:27 -0700187 final boolean wasResizing = mResizing;
Chong Zhang3005e752015-09-18 18:46:28 -0700188 synchronized (mService.mWindowMap) {
189 endDragLocked();
190 }
Chong Zhang09b21ef2015-09-14 10:20:21 -0700191 try {
Wale Ogunwale04ad7b12015-10-02 12:43:27 -0700192 if (wasResizing) {
Chong Zhang3005e752015-09-18 18:46:28 -0700193 // We were using fullscreen surface during resizing. Request
194 // resizeTask() one last time to restore surface to window size.
195 mService.mActivityManager.resizeTask(
Chong Zhang6de2ae82015-09-30 18:25:21 -0700196 mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
Chong Zhang3005e752015-09-18 18:46:28 -0700197 }
198
199 if (mCurrentDimSide != CTRL_NONE) {
200 final int createMode = mCurrentDimSide == CTRL_LEFT
201 ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
202 : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
203 mService.mActivityManager.moveTaskToDockedStack(
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800204 mTask.mTaskId, createMode, true /*toTop*/, true /* animate */,
205 null /* initialBounds */);
Chong Zhang3005e752015-09-18 18:46:28 -0700206 }
Chong Zhang09b21ef2015-09-14 10:20:21 -0700207 } catch(RemoteException e) {}
Chong Zhang3005e752015-09-18 18:46:28 -0700208
Chong Zhang8e89b312015-09-09 15:09:30 -0700209 // Post back to WM to handle clean-ups. We still need the input
210 // event handler for the last finishInputEvent()!
211 mService.mH.sendEmptyMessage(H.FINISH_TASK_POSITIONING);
212 }
213 handled = true;
214 } catch (Exception e) {
215 Slog.e(TAG, "Exception caught by drag handleMotion", e);
216 } finally {
217 finishInputEvent(event, handled);
218 }
219 }
220 }
221
222 TaskPositioner(WindowManagerService service) {
223 mService = service;
224 }
225
226 /**
227 * @param display The Display that the window being dragged is on.
228 */
229 void register(Display display) {
230 if (DEBUG_TASK_POSITIONING) {
231 Slog.d(TAG, "Registering task positioner");
232 }
233
234 if (mClientChannel != null) {
235 Slog.e(TAG, "Task positioner already registered");
236 return;
237 }
238
239 mDisplay = display;
240 mDisplay.getMetrics(mDisplayMetrics);
241 final InputChannel[] channels = InputChannel.openInputChannelPair(TAG);
242 mServerChannel = channels[0];
243 mClientChannel = channels[1];
244 mService.mInputManager.registerInputChannel(mServerChannel, null);
245
Wale Ogunwale4f52bc62015-09-24 13:47:31 -0700246 mInputEventReceiver = new WindowPositionerEventReceiver(
247 mClientChannel, mService.mH.getLooper(), mService.mChoreographer);
Chong Zhang8e89b312015-09-09 15:09:30 -0700248
249 mDragApplicationHandle = new InputApplicationHandle(null);
250 mDragApplicationHandle.name = TAG;
251 mDragApplicationHandle.dispatchingTimeoutNanos =
252 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
253
254 mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
255 mDisplay.getDisplayId());
256 mDragWindowHandle.name = TAG;
257 mDragWindowHandle.inputChannel = mServerChannel;
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700258 mDragWindowHandle.layer = mService.getDragLayerLocked();
Chong Zhang8e89b312015-09-09 15:09:30 -0700259 mDragWindowHandle.layoutParamsFlags = 0;
260 mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
261 mDragWindowHandle.dispatchingTimeoutNanos =
262 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
263 mDragWindowHandle.visible = true;
264 mDragWindowHandle.canReceiveKeys = false;
265 mDragWindowHandle.hasFocus = true;
266 mDragWindowHandle.hasWallpaper = false;
267 mDragWindowHandle.paused = false;
268 mDragWindowHandle.ownerPid = Process.myPid();
269 mDragWindowHandle.ownerUid = Process.myUid();
270 mDragWindowHandle.inputFeatures = 0;
271 mDragWindowHandle.scaleFactor = 1.0f;
272
273 // The drag window cannot receive new touches.
274 mDragWindowHandle.touchableRegion.setEmpty();
275
276 // The drag window covers the entire display
277 mDragWindowHandle.frameLeft = 0;
278 mDragWindowHandle.frameTop = 0;
279 final Point p = new Point();
280 mDisplay.getRealSize(p);
281 mDragWindowHandle.frameRight = p.x;
282 mDragWindowHandle.frameBottom = p.y;
283
284 // Pause rotations before a drag.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800285 if (DEBUG_ORIENTATION) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700286 Slog.d(TAG, "Pausing rotation during re-position");
287 }
288 mService.pauseRotationLocked();
Wale Ogunwale228d4042015-09-13 10:17:34 -0700289
290 mDimLayer = new DimLayer(mService, this, mDisplay.getDisplayId());
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700291 mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
292 mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
293 mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700294
295 mDragEnded = false;
Chong Zhang8e89b312015-09-09 15:09:30 -0700296 }
297
298 void unregister() {
299 if (DEBUG_TASK_POSITIONING) {
300 Slog.d(TAG, "Unregistering task positioner");
301 }
302
303 if (mClientChannel == null) {
304 Slog.e(TAG, "Task positioner not registered");
305 return;
306 }
307
308 mService.mInputManager.unregisterInputChannel(mServerChannel);
309
310 mInputEventReceiver.dispose();
311 mInputEventReceiver = null;
312 mClientChannel.dispose();
313 mServerChannel.dispose();
314 mClientChannel = null;
315 mServerChannel = null;
316
317 mDragWindowHandle = null;
318 mDragApplicationHandle = null;
319 mDisplay = null;
320
Wale Ogunwale228d4042015-09-13 10:17:34 -0700321 if (mDimLayer != null) {
322 mDimLayer.destroySurface();
323 mDimLayer = null;
324 }
325 mCurrentDimSide = CTRL_NONE;
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700326 mDragEnded = true;
Wale Ogunwale228d4042015-09-13 10:17:34 -0700327
Chong Zhang8e89b312015-09-09 15:09:30 -0700328 // Resume rotations after a drag.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800329 if (DEBUG_ORIENTATION) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700330 Slog.d(TAG, "Resuming rotation after re-position");
331 }
332 mService.resumeRotationLocked();
333 }
334
335 void startDragLocked(WindowState win, boolean resize, float startX, float startY) {
Wale Ogunwale228d4042015-09-13 10:17:34 -0700336 if (DEBUG_TASK_POSITIONING) {
337 Slog.d(TAG, "startDragLocked: win=" + win + ", resize=" + resize
Chong Zhang8e89b312015-09-09 15:09:30 -0700338 + ", {" + startX + ", " + startY + "}");
339 }
340 mCtrlType = CTRL_NONE;
Chong Zhangd8ceb852015-11-11 14:53:41 -0800341 mTask = win.getTask();
342 mStartDragX = startX;
343 mStartDragY = startY;
344
Chong Zhangb15758a2015-11-17 12:12:03 -0800345 if (mTask.isDockedInEffect()) {
346 // If this is a docked task or if task size is affected by docked stack changing size,
347 // we can only be here if the task is not resizeable and we're handling a two-finger
348 // scrolling. Use the original task bounds to position the task, the dim bounds
349 // is cropped and doesn't move.
350 mTask.getBounds(mTmpRect);
351 } else {
352 // Use the dim bounds, not the original task bounds. The cursor
353 // movement should be calculated relative to the visible bounds.
354 // Also, use the dim bounds of the task which accounts for
355 // multiple app windows. Don't use any bounds from win itself as it
356 // may not be the same size as the task.
357 mTask.getDimBounds(mTmpRect);
358 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800359
Chong Zhang8e89b312015-09-09 15:09:30 -0700360 if (resize) {
Chong Zhangd8ceb852015-11-11 14:53:41 -0800361 if (startX < mTmpRect.left) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700362 mCtrlType |= CTRL_LEFT;
363 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800364 if (startX > mTmpRect.right) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700365 mCtrlType |= CTRL_RIGHT;
366 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800367 if (startY < mTmpRect.top) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700368 mCtrlType |= CTRL_TOP;
369 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800370 if (startY > mTmpRect.bottom) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700371 mCtrlType |= CTRL_BOTTOM;
372 }
Chong Zhang09b21ef2015-09-14 10:20:21 -0700373 mResizing = true;
Chong Zhang8e89b312015-09-09 15:09:30 -0700374 }
375
Chong Zhangd8ceb852015-11-11 14:53:41 -0800376 mWindowOriginalBounds.set(mTmpRect);
Chong Zhang3005e752015-09-18 18:46:28 -0700377 }
378
379 private void endDragLocked() {
380 mResizing = false;
381 mTask.setDragResizing(false);
Chong Zhang8e89b312015-09-09 15:09:30 -0700382 }
383
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700384 /** Returns true if the move operation should be ended. */
385 private boolean notifyMoveLocked(float x, float y) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700386 if (DEBUG_TASK_POSITIONING) {
Chong Zhangb15758a2015-11-17 12:12:03 -0800387 Slog.d(TAG, "notifyMoveLocked: {" + x + "," + y + "}");
Chong Zhang8e89b312015-09-09 15:09:30 -0700388 }
389
390 if (mCtrlType != CTRL_NONE) {
391 // This is a resizing operation.
392 final int deltaX = Math.round(x - mStartDragX);
393 final int deltaY = Math.round(y - mStartDragY);
Chong Zhang8e89b312015-09-09 15:09:30 -0700394 int left = mWindowOriginalBounds.left;
395 int top = mWindowOriginalBounds.top;
396 int right = mWindowOriginalBounds.right;
397 int bottom = mWindowOriginalBounds.bottom;
398 if ((mCtrlType & CTRL_LEFT) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700399 left = Math.min(left + deltaX, right - mMinVisibleWidth);
Chong Zhang8e89b312015-09-09 15:09:30 -0700400 }
401 if ((mCtrlType & CTRL_TOP) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700402 top = Math.min(top + deltaY, bottom - mMinVisibleHeight);
Chong Zhang8e89b312015-09-09 15:09:30 -0700403 }
404 if ((mCtrlType & CTRL_RIGHT) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700405 right = Math.max(left + mMinVisibleWidth, right + deltaX);
Chong Zhang8e89b312015-09-09 15:09:30 -0700406 }
407 if ((mCtrlType & CTRL_BOTTOM) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700408 bottom = Math.max(top + mMinVisibleHeight, bottom + deltaY);
Chong Zhang8e89b312015-09-09 15:09:30 -0700409 }
410 mWindowDragBounds.set(left, top, right, bottom);
Chong Zhang3005e752015-09-18 18:46:28 -0700411 mTask.setDragResizing(true);
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700412 return false;
Chong Zhang8e89b312015-09-09 15:09:30 -0700413 }
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700414
415 // This is a moving operation.
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800416 mTask.mStack.getDimBounds(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -0800417
418 // If this is a non-resizeable task put into side-by-side mode, we are
419 // handling a two-finger scrolling action. No need to shrink the bounds.
420 if (!mTask.isDockedInEffect()) {
421 mTmpRect.inset(mMinVisibleWidth, mMinVisibleHeight);
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700422 }
Chong Zhangb15758a2015-11-17 12:12:03 -0800423
424 boolean dragEnded = false;
425 final int nX = (int) x;
426 final int nY = (int) y;
427 if (!mTmpRect.contains(nX, nY)) {
428 // We end the moving operation if position is outside the stack bounds.
429 // In this case we need to clamp the position to stack bounds and calculate
430 // the final window drag bounds.
431 x = Math.min(Math.max(x, mTmpRect.left), mTmpRect.right);
432 y = Math.min(Math.max(y, mTmpRect.top), mTmpRect.bottom);
433 dragEnded = true;
434 }
435
436 updateWindowDragBounds(nX, nY);
437 updateDimLayerVisibility(nX);
438 return dragEnded;
439 }
440
441 private void updateWindowDragBounds(int x, int y) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700442 mWindowDragBounds.set(mWindowOriginalBounds);
Chong Zhangb15758a2015-11-17 12:12:03 -0800443 if (mTask.isDockedInEffect()) {
444 // Offset the bounds without clamp, the bounds will be shifted later
445 // by window manager before applying the scrolling.
446 if (mService.mCurConfiguration.orientation == ORIENTATION_LANDSCAPE) {
447 mWindowDragBounds.offset(Math.round(x - mStartDragX), 0);
448 } else {
449 mWindowDragBounds.offset(0, Math.round(y - mStartDragY));
450 }
451 } else {
452 mWindowDragBounds.offset(Math.round(x - mStartDragX), Math.round(y - mStartDragY));
453 }
454 if (DEBUG_TASK_POSITIONING) Slog.d(TAG,
455 "updateWindowDragBounds: " + mWindowDragBounds);
Chong Zhang8e89b312015-09-09 15:09:30 -0700456 }
457
Wale Ogunwale228d4042015-09-13 10:17:34 -0700458 private void updateDimLayerVisibility(int x) {
459 @CtrlType
460 int dimSide = getDimSide(x);
461 if (dimSide == mCurrentDimSide) {
462 return;
463 }
464
465 mCurrentDimSide = dimSide;
466
467 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION updateDimLayerVisibility");
468 SurfaceControl.openTransaction();
469 if (mCurrentDimSide == CTRL_NONE) {
470 mDimLayer.hide();
471 } else {
472 showDimLayer();
473 }
474 SurfaceControl.closeTransaction();
475 }
476
477 /**
478 * Returns the side of the screen the dim layer should be shown.
479 * @param x horizontal coordinate used to determine if the dim layer should be shown
480 * @return Returns {@link #CTRL_LEFT} if the dim layer should be shown on the left half of the
481 * screen, {@link #CTRL_RIGHT} if on the right side, or {@link #CTRL_NONE} if the dim layer
482 * shouldn't be shown.
483 */
484 private int getDimSide(int x) {
Chong Zhang3005e752015-09-18 18:46:28 -0700485 if (mTask.mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
486 || !mTask.mStack.isFullscreen()
Wale Ogunwale228d4042015-09-13 10:17:34 -0700487 || mService.mCurConfiguration.orientation != ORIENTATION_LANDSCAPE) {
488 return CTRL_NONE;
489 }
490
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800491 mTask.mStack.getDimBounds(mTmpRect);
Wale Ogunwale228d4042015-09-13 10:17:34 -0700492 if (x - mSideMargin <= mTmpRect.left) {
493 return CTRL_LEFT;
494 }
495 if (x + mSideMargin >= mTmpRect.right) {
496 return CTRL_RIGHT;
497 }
498
499 return CTRL_NONE;
500 }
501
502 private void showDimLayer() {
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800503 mTask.mStack.getDimBounds(mTmpRect);
Wale Ogunwale228d4042015-09-13 10:17:34 -0700504 if (mCurrentDimSide == CTRL_LEFT) {
505 mTmpRect.right = mTmpRect.centerX();
506 } else if (mCurrentDimSide == CTRL_RIGHT) {
507 mTmpRect.left = mTmpRect.centerX();
508 }
509
510 mDimLayer.setBounds(mTmpRect);
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700511 mDimLayer.show(mService.getDragLayerLocked(), RESIZING_HINT_ALPHA,
512 RESIZING_HINT_DURATION_MS);
Wale Ogunwale228d4042015-09-13 10:17:34 -0700513 }
514
515 @Override /** {@link DimLayer.DimLayerUser} */
516 public boolean isFullscreen() {
517 return false;
518 }
519
520 @Override /** {@link DimLayer.DimLayerUser} */
521 public DisplayInfo getDisplayInfo() {
Chong Zhang3005e752015-09-18 18:46:28 -0700522 return mTask.mStack.getDisplayInfo();
Wale Ogunwale228d4042015-09-13 10:17:34 -0700523 }
524
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700525 @Override
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800526 public void getDimBounds(Rect out) {
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700527 // This dim layer user doesn't need this.
528 }
529
530 @Override
531 public String toShortString() {
532 return TAG;
533 }
Wale Ogunwale228d4042015-09-13 10:17:34 -0700534}