blob: 32c320560ce8ac35818843d4e4cea4fa561b5096 [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;
Wale Ogunwale3797c222015-10-27 14:21:58 -070021import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
Chong Zhang87b21722015-09-21 15:39:51 -070022import static android.app.ActivityManager.RESIZE_MODE_USER;
Chong Zhang6de2ae82015-09-30 18:25:21 -070023import static android.app.ActivityManager.RESIZE_MODE_USER_FORCED;
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;
Chong Zhang8e89b312015-09-09 15:09:30 -070028import static com.android.server.wm.WindowManagerService.DEBUG_TASK_POSITIONING;
Wale Ogunwale228d4042015-09-13 10:17:34 -070029import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS;
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -070030import static com.android.server.wm.WindowManagerService.dipToPixel;
Wale Ogunwale231b06e2015-09-16 12:03:09 -070031import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
32import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
Chong Zhang8e89b312015-09-09 15:09:30 -070033
34import android.annotation.IntDef;
35import android.graphics.Point;
36import android.graphics.Rect;
37import android.os.Looper;
38import android.os.Process;
39import android.os.RemoteException;
Wale Ogunwalecad05a02015-09-25 10:41:44 -070040import android.os.Trace;
Chong Zhang8e89b312015-09-09 15:09:30 -070041import android.util.DisplayMetrics;
42import android.util.Slog;
Wale Ogunwale4f52bc62015-09-24 13:47:31 -070043import android.view.Choreographer;
Chong Zhang8e89b312015-09-09 15:09:30 -070044import android.view.Display;
Wale Ogunwale228d4042015-09-13 10:17:34 -070045import android.view.DisplayInfo;
Chong Zhang8e89b312015-09-09 15:09:30 -070046import android.view.InputChannel;
47import android.view.InputDevice;
48import android.view.InputEvent;
Wale Ogunwale4f52bc62015-09-24 13:47:31 -070049import android.view.BatchedInputEventReceiver;
Chong Zhang8e89b312015-09-09 15:09:30 -070050import android.view.MotionEvent;
Wale Ogunwale228d4042015-09-13 10:17:34 -070051import android.view.SurfaceControl;
Chong Zhang8e89b312015-09-09 15:09:30 -070052import android.view.WindowManager;
53
Wale Ogunwale228d4042015-09-13 10:17:34 -070054import com.android.server.input.InputApplicationHandle;
55import com.android.server.input.InputWindowHandle;
56import com.android.server.wm.WindowManagerService.H;
57
58import java.lang.annotation.Retention;
59import java.lang.annotation.RetentionPolicy;
60
61class TaskPositioner implements DimLayer.DimLayerUser {
Chong Zhang8e89b312015-09-09 15:09:30 -070062 private static final String TAG = "TaskPositioner";
63
Wale Ogunwale228d4042015-09-13 10:17:34 -070064 // The margin the pointer position has to be within the side of the screen to be
65 // considered at the side of the screen.
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -070066 static final int SIDE_MARGIN_DIP = 100;
Wale Ogunwale228d4042015-09-13 10:17:34 -070067
Chong Zhang8e89b312015-09-09 15:09:30 -070068 @IntDef(flag = true,
69 value = {
70 CTRL_NONE,
71 CTRL_LEFT,
72 CTRL_RIGHT,
73 CTRL_TOP,
74 CTRL_BOTTOM
75 })
76 @Retention(RetentionPolicy.SOURCE)
77 @interface CtrlType {}
78
79 private static final int CTRL_NONE = 0x0;
80 private static final int CTRL_LEFT = 0x1;
81 private static final int CTRL_RIGHT = 0x2;
82 private static final int CTRL_TOP = 0x4;
83 private static final int CTRL_BOTTOM = 0x8;
84
85 private final WindowManagerService mService;
86 private WindowPositionerEventReceiver mInputEventReceiver;
87 private Display mDisplay;
88 private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
Wale Ogunwale228d4042015-09-13 10:17:34 -070089 private DimLayer mDimLayer;
90 @CtrlType
91 private int mCurrentDimSide;
92 private Rect mTmpRect = new Rect();
93 private int mSideMargin;
Wale Ogunwaleb8051b82015-09-17 15:41:52 -070094 private int mMinVisibleWidth;
95 private int mMinVisibleHeight;
Chong Zhang8e89b312015-09-09 15:09:30 -070096
Chong Zhang3005e752015-09-18 18:46:28 -070097 private Task mTask;
Chong Zhang09b21ef2015-09-14 10:20:21 -070098 private boolean mResizing;
Chong Zhang8e89b312015-09-09 15:09:30 -070099 private final Rect mWindowOriginalBounds = new Rect();
100 private final Rect mWindowDragBounds = new Rect();
101 private float mStartDragX;
102 private float mStartDragY;
103 @CtrlType
104 private int mCtrlType = CTRL_NONE;
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700105 private boolean mDragEnded = false;
Chong Zhang8e89b312015-09-09 15:09:30 -0700106
107 InputChannel mServerChannel;
108 InputChannel mClientChannel;
109 InputApplicationHandle mDragApplicationHandle;
110 InputWindowHandle mDragWindowHandle;
111
Wale Ogunwale4f52bc62015-09-24 13:47:31 -0700112 private final class WindowPositionerEventReceiver extends BatchedInputEventReceiver {
113 public WindowPositionerEventReceiver(
114 InputChannel inputChannel, Looper looper, Choreographer choreographer) {
115 super(inputChannel, looper, choreographer);
Chong Zhang8e89b312015-09-09 15:09:30 -0700116 }
117
118 @Override
119 public void onInputEvent(InputEvent event) {
120 if (!(event instanceof MotionEvent)
121 || (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
122 return;
123 }
124 final MotionEvent motionEvent = (MotionEvent) event;
125 boolean handled = false;
126
127 try {
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700128 if (mDragEnded) {
129 // The drag has ended but the clean-up message has not been processed by
130 // window manager. Drop events that occur after this until window manager
131 // has a chance to clean-up the input handle.
132 handled = true;
133 return;
134 }
135
Chong Zhang8e89b312015-09-09 15:09:30 -0700136 final float newX = motionEvent.getRawX();
137 final float newY = motionEvent.getRawY();
138
139 switch (motionEvent.getAction()) {
140 case MotionEvent.ACTION_DOWN: {
141 if (DEBUG_TASK_POSITIONING) {
142 Slog.w(TAG, "ACTION_DOWN @ {" + newX + ", " + newY + "}");
143 }
144 } break;
145
146 case MotionEvent.ACTION_MOVE: {
147 if (DEBUG_TASK_POSITIONING){
148 Slog.w(TAG, "ACTION_MOVE @ {" + newX + ", " + newY + "}");
149 }
150 synchronized (mService.mWindowMap) {
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700151 mDragEnded = notifyMoveLocked(newX, newY);
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800152 mTask.getDimBounds(mTmpRect);
Chong Zhang8e89b312015-09-09 15:09:30 -0700153 }
Wale Ogunwale04ad7b12015-10-02 12:43:27 -0700154 if (!mTmpRect.equals(mWindowDragBounds)) {
155 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
156 "wm.TaskPositioner.resizeTask");
157 try {
158 mService.mActivityManager.resizeTask(
159 mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
160 } catch (RemoteException e) {
161 }
162 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
163 }
Chong Zhang8e89b312015-09-09 15:09:30 -0700164 } break;
165
166 case MotionEvent.ACTION_UP: {
167 if (DEBUG_TASK_POSITIONING) {
168 Slog.w(TAG, "ACTION_UP @ {" + newX + ", " + newY + "}");
169 }
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700170 mDragEnded = true;
Chong Zhang8e89b312015-09-09 15:09:30 -0700171 } break;
172
173 case MotionEvent.ACTION_CANCEL: {
174 if (DEBUG_TASK_POSITIONING) {
175 Slog.w(TAG, "ACTION_CANCEL @ {" + newX + ", " + newY + "}");
176 }
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700177 mDragEnded = true;
Chong Zhang8e89b312015-09-09 15:09:30 -0700178 } break;
179 }
180
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700181 if (mDragEnded) {
Wale Ogunwale04ad7b12015-10-02 12:43:27 -0700182 final boolean wasResizing = mResizing;
Chong Zhang3005e752015-09-18 18:46:28 -0700183 synchronized (mService.mWindowMap) {
184 endDragLocked();
185 }
Chong Zhang09b21ef2015-09-14 10:20:21 -0700186 try {
Wale Ogunwale04ad7b12015-10-02 12:43:27 -0700187 if (wasResizing) {
Chong Zhang3005e752015-09-18 18:46:28 -0700188 // We were using fullscreen surface during resizing. Request
189 // resizeTask() one last time to restore surface to window size.
190 mService.mActivityManager.resizeTask(
Chong Zhang6de2ae82015-09-30 18:25:21 -0700191 mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
Chong Zhang3005e752015-09-18 18:46:28 -0700192 }
193
194 if (mCurrentDimSide != CTRL_NONE) {
195 final int createMode = mCurrentDimSide == CTRL_LEFT
196 ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
197 : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
198 mService.mActivityManager.moveTaskToDockedStack(
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800199 mTask.mTaskId, createMode, true /*toTop*/, true /* animate */,
200 null /* initialBounds */);
Chong Zhang3005e752015-09-18 18:46:28 -0700201 }
Chong Zhang09b21ef2015-09-14 10:20:21 -0700202 } catch(RemoteException e) {}
Chong Zhang3005e752015-09-18 18:46:28 -0700203
Chong Zhang8e89b312015-09-09 15:09:30 -0700204 // Post back to WM to handle clean-ups. We still need the input
205 // event handler for the last finishInputEvent()!
206 mService.mH.sendEmptyMessage(H.FINISH_TASK_POSITIONING);
207 }
208 handled = true;
209 } catch (Exception e) {
210 Slog.e(TAG, "Exception caught by drag handleMotion", e);
211 } finally {
212 finishInputEvent(event, handled);
213 }
214 }
215 }
216
217 TaskPositioner(WindowManagerService service) {
218 mService = service;
219 }
220
221 /**
222 * @param display The Display that the window being dragged is on.
223 */
224 void register(Display display) {
225 if (DEBUG_TASK_POSITIONING) {
226 Slog.d(TAG, "Registering task positioner");
227 }
228
229 if (mClientChannel != null) {
230 Slog.e(TAG, "Task positioner already registered");
231 return;
232 }
233
234 mDisplay = display;
235 mDisplay.getMetrics(mDisplayMetrics);
236 final InputChannel[] channels = InputChannel.openInputChannelPair(TAG);
237 mServerChannel = channels[0];
238 mClientChannel = channels[1];
239 mService.mInputManager.registerInputChannel(mServerChannel, null);
240
Wale Ogunwale4f52bc62015-09-24 13:47:31 -0700241 mInputEventReceiver = new WindowPositionerEventReceiver(
242 mClientChannel, mService.mH.getLooper(), mService.mChoreographer);
Chong Zhang8e89b312015-09-09 15:09:30 -0700243
244 mDragApplicationHandle = new InputApplicationHandle(null);
245 mDragApplicationHandle.name = TAG;
246 mDragApplicationHandle.dispatchingTimeoutNanos =
247 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
248
249 mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
250 mDisplay.getDisplayId());
251 mDragWindowHandle.name = TAG;
252 mDragWindowHandle.inputChannel = mServerChannel;
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700253 mDragWindowHandle.layer = mService.getDragLayerLocked();
Chong Zhang8e89b312015-09-09 15:09:30 -0700254 mDragWindowHandle.layoutParamsFlags = 0;
255 mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
256 mDragWindowHandle.dispatchingTimeoutNanos =
257 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
258 mDragWindowHandle.visible = true;
259 mDragWindowHandle.canReceiveKeys = false;
260 mDragWindowHandle.hasFocus = true;
261 mDragWindowHandle.hasWallpaper = false;
262 mDragWindowHandle.paused = false;
263 mDragWindowHandle.ownerPid = Process.myPid();
264 mDragWindowHandle.ownerUid = Process.myUid();
265 mDragWindowHandle.inputFeatures = 0;
266 mDragWindowHandle.scaleFactor = 1.0f;
267
268 // The drag window cannot receive new touches.
269 mDragWindowHandle.touchableRegion.setEmpty();
270
271 // The drag window covers the entire display
272 mDragWindowHandle.frameLeft = 0;
273 mDragWindowHandle.frameTop = 0;
274 final Point p = new Point();
275 mDisplay.getRealSize(p);
276 mDragWindowHandle.frameRight = p.x;
277 mDragWindowHandle.frameBottom = p.y;
278
279 // Pause rotations before a drag.
280 if (WindowManagerService.DEBUG_ORIENTATION) {
281 Slog.d(TAG, "Pausing rotation during re-position");
282 }
283 mService.pauseRotationLocked();
Wale Ogunwale228d4042015-09-13 10:17:34 -0700284
285 mDimLayer = new DimLayer(mService, this, mDisplay.getDisplayId());
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700286 mSideMargin = dipToPixel(SIDE_MARGIN_DIP, mDisplayMetrics);
287 mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, mDisplayMetrics);
288 mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, mDisplayMetrics);
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700289
290 mDragEnded = false;
Chong Zhang8e89b312015-09-09 15:09:30 -0700291 }
292
293 void unregister() {
294 if (DEBUG_TASK_POSITIONING) {
295 Slog.d(TAG, "Unregistering task positioner");
296 }
297
298 if (mClientChannel == null) {
299 Slog.e(TAG, "Task positioner not registered");
300 return;
301 }
302
303 mService.mInputManager.unregisterInputChannel(mServerChannel);
304
305 mInputEventReceiver.dispose();
306 mInputEventReceiver = null;
307 mClientChannel.dispose();
308 mServerChannel.dispose();
309 mClientChannel = null;
310 mServerChannel = null;
311
312 mDragWindowHandle = null;
313 mDragApplicationHandle = null;
314 mDisplay = null;
315
Wale Ogunwale228d4042015-09-13 10:17:34 -0700316 if (mDimLayer != null) {
317 mDimLayer.destroySurface();
318 mDimLayer = null;
319 }
320 mCurrentDimSide = CTRL_NONE;
Wale Ogunwale6a804b82015-09-23 21:04:21 -0700321 mDragEnded = true;
Wale Ogunwale228d4042015-09-13 10:17:34 -0700322
Chong Zhang8e89b312015-09-09 15:09:30 -0700323 // Resume rotations after a drag.
324 if (WindowManagerService.DEBUG_ORIENTATION) {
325 Slog.d(TAG, "Resuming rotation after re-position");
326 }
327 mService.resumeRotationLocked();
328 }
329
330 void startDragLocked(WindowState win, boolean resize, float startX, float startY) {
Wale Ogunwale228d4042015-09-13 10:17:34 -0700331 if (DEBUG_TASK_POSITIONING) {
332 Slog.d(TAG, "startDragLocked: win=" + win + ", resize=" + resize
Chong Zhang8e89b312015-09-09 15:09:30 -0700333 + ", {" + startX + ", " + startY + "}");
334 }
335 mCtrlType = CTRL_NONE;
Chong Zhangd8ceb852015-11-11 14:53:41 -0800336 mTask = win.getTask();
337 mStartDragX = startX;
338 mStartDragY = startY;
339
Chong Zhangb15758a2015-11-17 12:12:03 -0800340 if (mTask.isDockedInEffect()) {
341 // If this is a docked task or if task size is affected by docked stack changing size,
342 // we can only be here if the task is not resizeable and we're handling a two-finger
343 // scrolling. Use the original task bounds to position the task, the dim bounds
344 // is cropped and doesn't move.
345 mTask.getBounds(mTmpRect);
346 } else {
347 // Use the dim bounds, not the original task bounds. The cursor
348 // movement should be calculated relative to the visible bounds.
349 // Also, use the dim bounds of the task which accounts for
350 // multiple app windows. Don't use any bounds from win itself as it
351 // may not be the same size as the task.
352 mTask.getDimBounds(mTmpRect);
353 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800354
Chong Zhang8e89b312015-09-09 15:09:30 -0700355 if (resize) {
Chong Zhangd8ceb852015-11-11 14:53:41 -0800356 if (startX < mTmpRect.left) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700357 mCtrlType |= CTRL_LEFT;
358 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800359 if (startX > mTmpRect.right) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700360 mCtrlType |= CTRL_RIGHT;
361 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800362 if (startY < mTmpRect.top) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700363 mCtrlType |= CTRL_TOP;
364 }
Chong Zhangd8ceb852015-11-11 14:53:41 -0800365 if (startY > mTmpRect.bottom) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700366 mCtrlType |= CTRL_BOTTOM;
367 }
Chong Zhang09b21ef2015-09-14 10:20:21 -0700368 mResizing = true;
Chong Zhang8e89b312015-09-09 15:09:30 -0700369 }
370
Chong Zhangd8ceb852015-11-11 14:53:41 -0800371 mWindowOriginalBounds.set(mTmpRect);
Chong Zhang3005e752015-09-18 18:46:28 -0700372 }
373
374 private void endDragLocked() {
375 mResizing = false;
376 mTask.setDragResizing(false);
Chong Zhang8e89b312015-09-09 15:09:30 -0700377 }
378
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700379 /** Returns true if the move operation should be ended. */
380 private boolean notifyMoveLocked(float x, float y) {
Chong Zhang8e89b312015-09-09 15:09:30 -0700381 if (DEBUG_TASK_POSITIONING) {
Chong Zhangb15758a2015-11-17 12:12:03 -0800382 Slog.d(TAG, "notifyMoveLocked: {" + x + "," + y + "}");
Chong Zhang8e89b312015-09-09 15:09:30 -0700383 }
384
385 if (mCtrlType != CTRL_NONE) {
386 // This is a resizing operation.
387 final int deltaX = Math.round(x - mStartDragX);
388 final int deltaY = Math.round(y - mStartDragY);
Chong Zhang8e89b312015-09-09 15:09:30 -0700389 int left = mWindowOriginalBounds.left;
390 int top = mWindowOriginalBounds.top;
391 int right = mWindowOriginalBounds.right;
392 int bottom = mWindowOriginalBounds.bottom;
393 if ((mCtrlType & CTRL_LEFT) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700394 left = Math.min(left + deltaX, right - mMinVisibleWidth);
Chong Zhang8e89b312015-09-09 15:09:30 -0700395 }
396 if ((mCtrlType & CTRL_TOP) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700397 top = Math.min(top + deltaY, bottom - mMinVisibleHeight);
Chong Zhang8e89b312015-09-09 15:09:30 -0700398 }
399 if ((mCtrlType & CTRL_RIGHT) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700400 right = Math.max(left + mMinVisibleWidth, right + deltaX);
Chong Zhang8e89b312015-09-09 15:09:30 -0700401 }
402 if ((mCtrlType & CTRL_BOTTOM) != 0) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700403 bottom = Math.max(top + mMinVisibleHeight, bottom + deltaY);
Chong Zhang8e89b312015-09-09 15:09:30 -0700404 }
405 mWindowDragBounds.set(left, top, right, bottom);
Chong Zhang3005e752015-09-18 18:46:28 -0700406 mTask.setDragResizing(true);
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700407 return false;
Chong Zhang8e89b312015-09-09 15:09:30 -0700408 }
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700409
410 // This is a moving operation.
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800411 mTask.mStack.getDimBounds(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -0800412
413 // If this is a non-resizeable task put into side-by-side mode, we are
414 // handling a two-finger scrolling action. No need to shrink the bounds.
415 if (!mTask.isDockedInEffect()) {
416 mTmpRect.inset(mMinVisibleWidth, mMinVisibleHeight);
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700417 }
Chong Zhangb15758a2015-11-17 12:12:03 -0800418
419 boolean dragEnded = false;
420 final int nX = (int) x;
421 final int nY = (int) y;
422 if (!mTmpRect.contains(nX, nY)) {
423 // We end the moving operation if position is outside the stack bounds.
424 // In this case we need to clamp the position to stack bounds and calculate
425 // the final window drag bounds.
426 x = Math.min(Math.max(x, mTmpRect.left), mTmpRect.right);
427 y = Math.min(Math.max(y, mTmpRect.top), mTmpRect.bottom);
428 dragEnded = true;
429 }
430
431 updateWindowDragBounds(nX, nY);
432 updateDimLayerVisibility(nX);
433 return dragEnded;
434 }
435
436 private void updateWindowDragBounds(int x, int y) {
Wale Ogunwaleb8051b82015-09-17 15:41:52 -0700437 mWindowDragBounds.set(mWindowOriginalBounds);
Chong Zhangb15758a2015-11-17 12:12:03 -0800438 if (mTask.isDockedInEffect()) {
439 // Offset the bounds without clamp, the bounds will be shifted later
440 // by window manager before applying the scrolling.
441 if (mService.mCurConfiguration.orientation == ORIENTATION_LANDSCAPE) {
442 mWindowDragBounds.offset(Math.round(x - mStartDragX), 0);
443 } else {
444 mWindowDragBounds.offset(0, Math.round(y - mStartDragY));
445 }
446 } else {
447 mWindowDragBounds.offset(Math.round(x - mStartDragX), Math.round(y - mStartDragY));
448 }
449 if (DEBUG_TASK_POSITIONING) Slog.d(TAG,
450 "updateWindowDragBounds: " + mWindowDragBounds);
Chong Zhang8e89b312015-09-09 15:09:30 -0700451 }
452
Wale Ogunwale228d4042015-09-13 10:17:34 -0700453 private void updateDimLayerVisibility(int x) {
454 @CtrlType
455 int dimSide = getDimSide(x);
456 if (dimSide == mCurrentDimSide) {
457 return;
458 }
459
460 mCurrentDimSide = dimSide;
461
462 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION updateDimLayerVisibility");
463 SurfaceControl.openTransaction();
464 if (mCurrentDimSide == CTRL_NONE) {
465 mDimLayer.hide();
466 } else {
467 showDimLayer();
468 }
469 SurfaceControl.closeTransaction();
470 }
471
472 /**
473 * Returns the side of the screen the dim layer should be shown.
474 * @param x horizontal coordinate used to determine if the dim layer should be shown
475 * @return Returns {@link #CTRL_LEFT} if the dim layer should be shown on the left half of the
476 * screen, {@link #CTRL_RIGHT} if on the right side, or {@link #CTRL_NONE} if the dim layer
477 * shouldn't be shown.
478 */
479 private int getDimSide(int x) {
Chong Zhang3005e752015-09-18 18:46:28 -0700480 if (mTask.mStack.mStackId != FREEFORM_WORKSPACE_STACK_ID
481 || !mTask.mStack.isFullscreen()
Wale Ogunwale228d4042015-09-13 10:17:34 -0700482 || mService.mCurConfiguration.orientation != ORIENTATION_LANDSCAPE) {
483 return CTRL_NONE;
484 }
485
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800486 mTask.mStack.getDimBounds(mTmpRect);
Wale Ogunwale228d4042015-09-13 10:17:34 -0700487 if (x - mSideMargin <= mTmpRect.left) {
488 return CTRL_LEFT;
489 }
490 if (x + mSideMargin >= mTmpRect.right) {
491 return CTRL_RIGHT;
492 }
493
494 return CTRL_NONE;
495 }
496
497 private void showDimLayer() {
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800498 mTask.mStack.getDimBounds(mTmpRect);
Wale Ogunwale228d4042015-09-13 10:17:34 -0700499 if (mCurrentDimSide == CTRL_LEFT) {
500 mTmpRect.right = mTmpRect.centerX();
501 } else if (mCurrentDimSide == CTRL_RIGHT) {
502 mTmpRect.left = mTmpRect.centerX();
503 }
504
505 mDimLayer.setBounds(mTmpRect);
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700506 mDimLayer.show(mService.getDragLayerLocked(), RESIZING_HINT_ALPHA,
507 RESIZING_HINT_DURATION_MS);
Wale Ogunwale228d4042015-09-13 10:17:34 -0700508 }
509
510 @Override /** {@link DimLayer.DimLayerUser} */
511 public boolean isFullscreen() {
512 return false;
513 }
514
515 @Override /** {@link DimLayer.DimLayerUser} */
516 public DisplayInfo getDisplayInfo() {
Chong Zhang3005e752015-09-18 18:46:28 -0700517 return mTask.mStack.getDisplayInfo();
Wale Ogunwale228d4042015-09-13 10:17:34 -0700518 }
519
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700520 @Override
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800521 public void getDimBounds(Rect out) {
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700522 // This dim layer user doesn't need this.
523 }
524
525 @Override
526 public String toShortString() {
527 return TAG;
528 }
Wale Ogunwale228d4042015-09-13 10:17:34 -0700529}