blob: 725bbbc789851845500767fa4c4b78979ea36ed0 [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 Gruszczynski57b6cce2015-10-06 09:50:51 -070026import static com.android.server.wm.DimLayer.RESIZING_HINT_ALPHA;
27import static com.android.server.wm.DimLayer.RESIZING_HINT_DURATION_MS;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080028import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
29import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
30import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
31import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
32import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -070033import static com.android.server.wm.WindowManagerService.dipToPixel;
Wale Ogunwale231b06e2015-09-16 12:03:09 -070034import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
35import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
Chong Zhang8e89b312015-09-09 15:09:30 -070036
37import android.annotation.IntDef;
38import android.graphics.Point;
39import android.graphics.Rect;
40import android.os.Looper;
41import android.os.Process;
42import android.os.RemoteException;
Wale Ogunwalecad05a02015-09-25 10:41:44 -070043import android.os.Trace;
Chong Zhang8e89b312015-09-09 15:09:30 -070044import android.util.DisplayMetrics;
45import android.util.Slog;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080046import android.view.BatchedInputEventReceiver;
Wale Ogunwale4f52bc62015-09-24 13:47:31 -070047import android.view.Choreographer;
Chong Zhang8e89b312015-09-09 15:09:30 -070048import android.view.Display;
Wale Ogunwale228d4042015-09-13 10:17:34 -070049import android.view.DisplayInfo;
Chong Zhang8e89b312015-09-09 15:09:30 -070050import android.view.InputChannel;
51import android.view.InputDevice;
52import android.view.InputEvent;
Chong Zhang8e89b312015-09-09 15:09:30 -070053import android.view.MotionEvent;
Wale Ogunwale228d4042015-09-13 10:17:34 -070054import android.view.SurfaceControl;
Chong Zhang8e89b312015-09-09 15:09:30 -070055import android.view.WindowManager;
56
Wale Ogunwale228d4042015-09-13 10:17:34 -070057import com.android.server.input.InputApplicationHandle;
58import com.android.server.input.InputWindowHandle;
59import com.android.server.wm.WindowManagerService.H;
60
61import java.lang.annotation.Retention;
62import java.lang.annotation.RetentionPolicy;
63
64class TaskPositioner implements DimLayer.DimLayerUser {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080065 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskPositioner" : TAG_WM;
Chong Zhang8e89b312015-09-09 15:09:30 -070066
Wale Ogunwale228d4042015-09-13 10:17:34 -070067 // The margin the pointer position has to be within the side of the screen to be
68 // considered at the side of the screen.
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -070069 static final int SIDE_MARGIN_DIP = 100;
Wale Ogunwale228d4042015-09-13 10:17:34 -070070
Chong Zhang8e89b312015-09-09 15:09:30 -070071 @IntDef(flag = true,
72 value = {
73 CTRL_NONE,
74 CTRL_LEFT,
75 CTRL_RIGHT,
76 CTRL_TOP,
77 CTRL_BOTTOM
78 })
79 @Retention(RetentionPolicy.SOURCE)
80 @interface CtrlType {}
81
82 private static final int CTRL_NONE = 0x0;
83 private static final int CTRL_LEFT = 0x1;
84 private static final int CTRL_RIGHT = 0x2;
85 private static final int CTRL_TOP = 0x4;
86 private static final int CTRL_BOTTOM = 0x8;
87
88 private final WindowManagerService mService;
89 private WindowPositionerEventReceiver mInputEventReceiver;
90 private Display mDisplay;
91 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
Wale Ogunwale228d4042015-09-13 10:17:34 -070092 private DimLayer mDimLayer;
93 @CtrlType
94 private int mCurrentDimSide;
95 private Rect mTmpRect = new Rect();
96 private int mSideMargin;
Wale Ogunwaleb8051b82015-09-17 15:41:52 -070097 private int mMinVisibleWidth;
98 private int mMinVisibleHeight;
Chong Zhang8e89b312015-09-09 15:09:30 -070099
Chong Zhang3005e752015-09-18 18:46:28 -0700100 private Task mTask;
Chong Zhang09b21ef2015-09-14 10:20:21 -0700101 private boolean mResizing;
Chong Zhang8e89b312015-09-09 15:09:30 -0700102 private final Rect mWindowOriginalBounds = new Rect();
103 private final Rect mWindowDragBounds = new Rect();
104 private float mStartDragX;
105 private float mStartDragY;
106 @CtrlType
107 private int mCtrlType = CTRL_NONE;
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700108 private boolean mDragEnded = false;
Chong Zhang8e89b312015-09-09 15:09:30 -0700109
110 InputChannel mServerChannel;
111 InputChannel mClientChannel;
112 InputApplicationHandle mDragApplicationHandle;
113 InputWindowHandle mDragWindowHandle;
114
Wale Ogunwale4f52bc62015-09-24 13:47:31 -0700115 private final class WindowPositionerEventReceiver extends BatchedInputEventReceiver {
116 public WindowPositionerEventReceiver(
117 InputChannel inputChannel, Looper looper, Choreographer choreographer) {
118 super(inputChannel, looper, choreographer);
Chong Zhang8e89b312015-09-09 15:09:30 -0700119 }
120
121 @Override
122 public void onInputEvent(InputEvent event) {
123 if (!(event instanceof MotionEvent)
124 || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
125 return;
126 }
127 final MotionEvent motionEvent = (MotionEvent) event;
128 boolean handled = false;
129
130 try {
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700131 if (mDragEnded) {
132 // The drag has ended but the clean-up message has not been processed by
133 // window manager. Drop events that occur after this until window manager
134 // has a chance to clean-up the input handle.
135 handled = true;
136 return;
137 }
138
Chong Zhang8e89b312015-09-09 15:09:30 -0700139 final float newX = motionEvent.getRawX();
140 final float newY = motionEvent.getRawY();
141
142 switch (motionEvent.getAction()) {
143 case MotionEvent.ACTION_DOWN: {
144 if (DEBUG_TASK_POSITIONING) {
145 Slog.w(TAG, "ACTION_DOWN @ {" + newX + ", " + newY + "}");
146 }
147 } break;
148
149 case MotionEvent.ACTION_MOVE: {
150 if (DEBUG_TASK_POSITIONING){
151 Slog.w(TAG, "ACTION_MOVE @ {" + newX + ", " + newY + "}");
152 }
153 synchronized (mService.mWindowMap) {
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700154 mDragEnded = notifyMoveLocked(newX, newY);
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800155 mTask.getDimBounds(mTmpRect);
Chong Zhang8e89b312015-09-09 15:09:30 -0700156 }
Wale Ogunwale04ad7b12015-10-02 12:43:27 -0700157 if (!mTmpRect.equals(mWindowDragBounds)) {
158 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
159 "wm.TaskPositioner.resizeTask");
160 try {
161 mService.mActivityManager.resizeTask(
162 mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
163 } catch (RemoteException e) {
164 }
165 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
166 }
Chong Zhang8e89b312015-09-09 15:09:30 -0700167 } break;
168
169 case MotionEvent.ACTION_UP: {
170 if (DEBUG_TASK_POSITIONING) {
171 Slog.w(TAG, "ACTION_UP @ {" + newX + ", " + newY + "}");
172 }
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700173 mDragEnded = true;
Chong Zhang8e89b312015-09-09 15:09:30 -0700174 } break;
175
176 case MotionEvent.ACTION_CANCEL: {
177 if (DEBUG_TASK_POSITIONING) {
178 Slog.w(TAG, "ACTION_CANCEL @ {" + newX + ", " + newY + "}");
179 }
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700180 mDragEnded = true;
Chong Zhang8e89b312015-09-09 15:09:30 -0700181 } break;
182 }
183
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700184 if (mDragEnded) {
Wale Ogunwale04ad7b12015-10-02 12:43:27 -0700185 final boolean wasResizing = mResizing;
Chong Zhang3005e752015-09-18 18:46:28 -0700186 synchronized (mService.mWindowMap) {
187 endDragLocked();
188 }
Chong Zhang09b21ef2015-09-14 10:20:21 -0700189 try {
Wale Ogunwale04ad7b12015-10-02 12:43:27 -0700190 if (wasResizing) {
Chong Zhang3005e752015-09-18 18:46:28 -0700191 // We were using fullscreen surface during resizing. Request
192 // resizeTask() one last time to restore surface to window size.
193 mService.mActivityManager.resizeTask(
Chong Zhang6de2ae82015-09-30 18:25:21 -0700194 mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
Chong Zhang3005e752015-09-18 18:46:28 -0700195 }
196
197 if (mCurrentDimSide != CTRL_NONE) {
198 final int createMode = mCurrentDimSide == CTRL_LEFT
199 ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
200 : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
201 mService.mActivityManager.moveTaskToDockedStack(
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800202 mTask.mTaskId, createMode, true /*toTop*/, true /* animate */,
203 null /* initialBounds */);
Chong Zhang3005e752015-09-18 18:46:28 -0700204 }
Chong Zhang09b21ef2015-09-14 10:20:21 -0700205 } catch(RemoteException e) {}
Chong Zhang3005e752015-09-18 18:46:28 -0700206
Chong Zhang8e89b312015-09-09 15:09:30 -0700207 // Post back to WM to handle clean-ups. We still need the input
208 // event handler for the last finishInputEvent()!
209 mService.mH.sendEmptyMessage(H.FINISH_TASK_POSITIONING);
210 }
211 handled = true;
212 } catch (Exception e) {
213 Slog.e(TAG, "Exception caught by drag handleMotion", e);
214 } finally {
215 finishInputEvent(event, handled);
216 }
217 }
218 }
219
220 TaskPositioner(WindowManagerService service) {
221 mService = service;
222 }
223
224 /**
225 * @param display The Display that the window being dragged is on.
226 */
227 void register(Display display) {
228 if (DEBUG_TASK_POSITIONING) {
229 Slog.d(TAG, "Registering task positioner");
230 }
231
232 if (mClientChannel != null) {
233 Slog.e(TAG, "Task positioner already registered");
234 return;
235 }
236
237 mDisplay = display;
238 mDisplay.getMetrics(mDisplayMetrics);
239 final InputChannel[] channels = InputChannel.openInputChannelPair(TAG);
240 mServerChannel = channels[0];
241 mClientChannel = channels[1];
242 mService.mInputManager.registerInputChannel(mServerChannel, null);
243
Wale Ogunwale4f52bc62015-09-24 13:47:31 -0700244 mInputEventReceiver = new WindowPositionerEventReceiver(
245 mClientChannel, mService.mH.getLooper(), mService.mChoreographer);
Chong Zhang8e89b312015-09-09 15:09:30 -0700246
247 mDragApplicationHandle = new InputApplicationHandle(null);
248 mDragApplicationHandle.name = TAG;
249 mDragApplicationHandle.dispatchingTimeoutNanos =
250 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
251
252 mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
253 mDisplay.getDisplayId());
254 mDragWindowHandle.name = TAG;
255 mDragWindowHandle.inputChannel = mServerChannel;
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700256 mDragWindowHandle.layer = mService.getDragLayerLocked();
Chong Zhang8e89b312015-09-09 15:09:30 -0700257 mDragWindowHandle.layoutParamsFlags = 0;
258 mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
259 mDragWindowHandle.dispatchingTimeoutNanos =
260 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
261 mDragWindowHandle.visible = true;
262 mDragWindowHandle.canReceiveKeys = false;
263 mDragWindowHandle.hasFocus = true;
264 mDragWindowHandle.hasWallpaper = false;
265 mDragWindowHandle.paused = false;
266 mDragWindowHandle.ownerPid = Process.myPid();
267 mDragWindowHandle.ownerUid = Process.myUid();
268 mDragWindowHandle.inputFeatures = 0;
269 mDragWindowHandle.scaleFactor = 1.0f;
270
271 // The drag window cannot receive new touches.
272 mDragWindowHandle.touchableRegion.setEmpty();
273
274 // The drag window covers the entire display
275 mDragWindowHandle.frameLeft = 0;
276 mDragWindowHandle.frameTop = 0;
277 final Point p = new Point();
278 mDisplay.getRealSize(p);
279 mDragWindowHandle.frameRight = p.x;
280 mDragWindowHandle.frameBottom = p.y;
281
282 // Pause rotations before a drag.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800283 if (DEBUG_ORIENTATION) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700284 Slog.d(TAG, "Pausing rotation during re-position");
285 }
286 mService.pauseRotationLocked();
Wale Ogunwale228d4042015-09-13 10:17:34 -0700287
288 mDimLayer = new DimLayer(mService, this, mDisplay.getDisplayId());
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700289 mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
290 mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
291 mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700292
293 mDragEnded = false;
Chong Zhang8e89b312015-09-09 15:09:30 -0700294 }
295
296 void unregister() {
297 if (DEBUG_TASK_POSITIONING) {
298 Slog.d(TAG, "Unregistering task positioner");
299 }
300
301 if (mClientChannel == null) {
302 Slog.e(TAG, "Task positioner not registered");
303 return;
304 }
305
306 mService.mInputManager.unregisterInputChannel(mServerChannel);
307
308 mInputEventReceiver.dispose();
309 mInputEventReceiver = null;
310 mClientChannel.dispose();
311 mServerChannel.dispose();
312 mClientChannel = null;
313 mServerChannel = null;
314
315 mDragWindowHandle = null;
316 mDragApplicationHandle = null;
317 mDisplay = null;
318
Wale Ogunwale228d4042015-09-13 10:17:34 -0700319 if (mDimLayer != null) {
320 mDimLayer.destroySurface();
321 mDimLayer = null;
322 }
323 mCurrentDimSide = CTRL_NONE;
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700324 mDragEnded = true;
Wale Ogunwale228d4042015-09-13 10:17:34 -0700325
Chong Zhang8e89b312015-09-09 15:09:30 -0700326 // Resume rotations after a drag.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800327 if (DEBUG_ORIENTATION) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700328 Slog.d(TAG, "Resuming rotation after re-position");
329 }
330 mService.resumeRotationLocked();
331 }
332
333 void startDragLocked(WindowState win, boolean resize, float startX, float startY) {
Wale Ogunwale228d4042015-09-13 10:17:34 -0700334 if (DEBUG_TASK_POSITIONING) {
335 Slog.d(TAG, "startDragLocked: win=" + win + ", resize=" + resize
Chong Zhang8e89b312015-09-09 15:09:30 -0700336 + ", {" + startX + ", " + startY + "}");
337 }
338 mCtrlType = CTRL_NONE;
Chong Zhangd8ceb852015-11-11 14:53:41 -0800339 mTask = win.getTask();
340 mStartDragX = startX;
341 mStartDragY = startY;
342
Chong Zhangb15758a2015-11-17 12:12:03 -0800343 if (mTask.isDockedInEffect()) {
344 // If this is a docked task or if task size is affected by docked stack changing size,
345 // we can only be here if the task is not resizeable and we're handling a two-finger
346 // scrolling. Use the original task bounds to position the task, the dim bounds
347 // is cropped and doesn't move.
348 mTask.getBounds(mTmpRect);
349 } else {
350 // Use the dim bounds, not the original task bounds. The cursor
351 // movement should be calculated relative to the visible bounds.
352 // Also, use the dim bounds of the task which accounts for
353 // multiple app windows. Don't use any bounds from win itself as it
354 // may not be the same size as the task.
355 mTask.getDimBounds(mTmpRect);
356 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800357
Chong Zhang8e89b312015-09-09 15:09:30 -0700358 if (resize) {
Chong Zhangd8ceb852015-11-11 14:53:41 -0800359 if (startX < mTmpRect.left) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700360 mCtrlType |= CTRL_LEFT;
361 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800362 if (startX > mTmpRect.right) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700363 mCtrlType |= CTRL_RIGHT;
364 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800365 if (startY < mTmpRect.top) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700366 mCtrlType |= CTRL_TOP;
367 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800368 if (startY > mTmpRect.bottom) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700369 mCtrlType |= CTRL_BOTTOM;
370 }
Chong Zhang09b21ef2015-09-14 10:20:21 -0700371 mResizing = true;
Chong Zhang8e89b312015-09-09 15:09:30 -0700372 }
373
Chong Zhangd8ceb852015-11-11 14:53:41 -0800374 mWindowOriginalBounds.set(mTmpRect);
Chong Zhang3005e752015-09-18 18:46:28 -0700375 }
376
377 private void endDragLocked() {
378 mResizing = false;
379 mTask.setDragResizing(false);
Chong Zhang8e89b312015-09-09 15:09:30 -0700380 }
381
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700382 /** Returns true if the move operation should be ended. */
383 private boolean notifyMoveLocked(float x, float y) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700384 if (DEBUG_TASK_POSITIONING) {
Chong Zhangb15758a2015-11-17 12:12:03 -0800385 Slog.d(TAG, "notifyMoveLocked: {" + x + "," + y + "}");
Chong Zhang8e89b312015-09-09 15:09:30 -0700386 }
387
388 if (mCtrlType != CTRL_NONE) {
389 // This is a resizing operation.
390 final int deltaX = Math.round(x - mStartDragX);
391 final int deltaY = Math.round(y - mStartDragY);
Chong Zhang8e89b312015-09-09 15:09:30 -0700392 int left = mWindowOriginalBounds.left;
393 int top = mWindowOriginalBounds.top;
394 int right = mWindowOriginalBounds.right;
395 int bottom = mWindowOriginalBounds.bottom;
396 if ((mCtrlType & CTRL_LEFT) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700397 left = Math.min(left + deltaX, right - mMinVisibleWidth);
Chong Zhang8e89b312015-09-09 15:09:30 -0700398 }
399 if ((mCtrlType & CTRL_TOP) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700400 top = Math.min(top + deltaY, bottom - mMinVisibleHeight);
Chong Zhang8e89b312015-09-09 15:09:30 -0700401 }
402 if ((mCtrlType & CTRL_RIGHT) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700403 right = Math.max(left + mMinVisibleWidth, right + deltaX);
Chong Zhang8e89b312015-09-09 15:09:30 -0700404 }
405 if ((mCtrlType & CTRL_BOTTOM) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700406 bottom = Math.max(top + mMinVisibleHeight, bottom + deltaY);
Chong Zhang8e89b312015-09-09 15:09:30 -0700407 }
408 mWindowDragBounds.set(left, top, right, bottom);
Chong Zhang3005e752015-09-18 18:46:28 -0700409 mTask.setDragResizing(true);
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700410 return false;
Chong Zhang8e89b312015-09-09 15:09:30 -0700411 }
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700412
413 // This is a moving operation.
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800414 mTask.mStack.getDimBounds(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -0800415
416 // If this is a non-resizeable task put into side-by-side mode, we are
417 // handling a two-finger scrolling action. No need to shrink the bounds.
418 if (!mTask.isDockedInEffect()) {
419 mTmpRect.inset(mMinVisibleWidth, mMinVisibleHeight);
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700420 }
Chong Zhangb15758a2015-11-17 12:12:03 -0800421
422 boolean dragEnded = false;
423 final int nX = (int) x;
424 final int nY = (int) y;
425 if (!mTmpRect.contains(nX, nY)) {
426 // We end the moving operation if position is outside the stack bounds.
427 // In this case we need to clamp the position to stack bounds and calculate
428 // the final window drag bounds.
429 x = Math.min(Math.max(x, mTmpRect.left), mTmpRect.right);
430 y = Math.min(Math.max(y, mTmpRect.top), mTmpRect.bottom);
431 dragEnded = true;
432 }
433
434 updateWindowDragBounds(nX, nY);
435 updateDimLayerVisibility(nX);
436 return dragEnded;
437 }
438
439 private void updateWindowDragBounds(int x, int y) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700440 mWindowDragBounds.set(mWindowOriginalBounds);
Chong Zhangb15758a2015-11-17 12:12:03 -0800441 if (mTask.isDockedInEffect()) {
442 // Offset the bounds without clamp, the bounds will be shifted later
443 // by window manager before applying the scrolling.
444 if (mService.mCurConfiguration.orientation == ORIENTATION_LANDSCAPE) {
445 mWindowDragBounds.offset(Math.round(x - mStartDragX), 0);
446 } else {
447 mWindowDragBounds.offset(0, Math.round(y - mStartDragY));
448 }
449 } else {
450 mWindowDragBounds.offset(Math.round(x - mStartDragX), Math.round(y - mStartDragY));
451 }
452 if (DEBUG_TASK_POSITIONING) Slog.d(TAG,
453 "updateWindowDragBounds: " + mWindowDragBounds);
Chong Zhang8e89b312015-09-09 15:09:30 -0700454 }
455
Wale Ogunwale228d4042015-09-13 10:17:34 -0700456 private void updateDimLayerVisibility(int x) {
457 @CtrlType
458 int dimSide = getDimSide(x);
459 if (dimSide == mCurrentDimSide) {
460 return;
461 }
462
463 mCurrentDimSide = dimSide;
464
465 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION updateDimLayerVisibility");
466 SurfaceControl.openTransaction();
467 if (mCurrentDimSide == CTRL_NONE) {
468 mDimLayer.hide();
469 } else {
470 showDimLayer();
471 }
472 SurfaceControl.closeTransaction();
473 }
474
475 /**
476 * Returns the side of the screen the dim layer should be shown.
477 * @param x horizontal coordinate used to determine if the dim layer should be shown
478 * @return Returns {@link #CTRL_LEFT} if the dim layer should be shown on the left half of the
479 * screen, {@link #CTRL_RIGHT} if on the right side, or {@link #CTRL_NONE} if the dim layer
480 * shouldn't be shown.
481 */
482 private int getDimSide(int x) {
Chong Zhang3005e752015-09-18 18:46:28 -0700483 if (mTask.mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
484 || !mTask.mStack.isFullscreen()
Wale Ogunwale228d4042015-09-13 10:17:34 -0700485 || mService.mCurConfiguration.orientation != ORIENTATION_LANDSCAPE) {
486 return CTRL_NONE;
487 }
488
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800489 mTask.mStack.getDimBounds(mTmpRect);
Wale Ogunwale228d4042015-09-13 10:17:34 -0700490 if (x - mSideMargin <= mTmpRect.left) {
491 return CTRL_LEFT;
492 }
493 if (x + mSideMargin >= mTmpRect.right) {
494 return CTRL_RIGHT;
495 }
496
497 return CTRL_NONE;
498 }
499
500 private void showDimLayer() {
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800501 mTask.mStack.getDimBounds(mTmpRect);
Wale Ogunwale228d4042015-09-13 10:17:34 -0700502 if (mCurrentDimSide == CTRL_LEFT) {
503 mTmpRect.right = mTmpRect.centerX();
504 } else if (mCurrentDimSide == CTRL_RIGHT) {
505 mTmpRect.left = mTmpRect.centerX();
506 }
507
508 mDimLayer.setBounds(mTmpRect);
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700509 mDimLayer.show(mService.getDragLayerLocked(), RESIZING_HINT_ALPHA,
510 RESIZING_HINT_DURATION_MS);
Wale Ogunwale228d4042015-09-13 10:17:34 -0700511 }
512
513 @Override /** {@link DimLayer.DimLayerUser} */
514 public boolean isFullscreen() {
515 return false;
516 }
517
518 @Override /** {@link DimLayer.DimLayerUser} */
519 public DisplayInfo getDisplayInfo() {
Chong Zhang3005e752015-09-18 18:46:28 -0700520 return mTask.mStack.getDisplayInfo();
Wale Ogunwale228d4042015-09-13 10:17:34 -0700521 }
522
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700523 @Override
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800524 public void getDimBounds(Rect out) {
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700525 // This dim layer user doesn't need this.
526 }
527
528 @Override
529 public String toShortString() {
530 return TAG;
531 }
Wale Ogunwale228d4042015-09-13 10:17:34 -0700532}