blob: da894818519adc032d8225854e0ba9af41c163b2 [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
2 * Copyright (C) 2011 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
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080019import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
20import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
21import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
22import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
23import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080024
25import android.content.ClipData;
26import android.content.ClipDescription;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080027import android.graphics.Matrix;
Craig Mautner39834192012-09-02 07:47:24 -070028import android.graphics.Point;
Vladislav Kaznacheevc7ad0a02015-03-19 10:13:31 -070029import android.graphics.Rect;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080030import android.graphics.Region;
31import android.os.IBinder;
32import android.os.Message;
33import android.os.Process;
34import android.os.RemoteException;
35import android.util.Slog;
Craig Mautner39834192012-09-02 07:47:24 -070036import android.view.Display;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080037import android.view.DragEvent;
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -070038import android.view.DropPermissionHolder;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080039import android.view.InputChannel;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080040import android.view.SurfaceControl;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080041import android.view.View;
42import android.view.WindowManager;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080043import android.view.animation.AlphaAnimation;
44import android.view.animation.Animation;
45import android.view.animation.AnimationSet;
46import android.view.animation.DecelerateInterpolator;
47import android.view.animation.Interpolator;
48import android.view.animation.ScaleAnimation;
49import android.view.animation.Transformation;
50import android.view.animation.TranslateAnimation;
51
52import com.android.server.input.InputApplicationHandle;
53import com.android.server.input.InputWindowHandle;
54import com.android.server.wm.WindowManagerService.DragInputEventReceiver;
55import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080056
57import java.util.ArrayList;
58
59/**
60 * Drag/drop state
61 */
62class DragState {
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -080063 private static final long ANIMATION_DURATION_MS = 500;
64
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080065 final WindowManagerService mService;
66 IBinder mToken;
Mathias Agopian29479eb2013-02-14 14:36:04 -080067 SurfaceControl mSurfaceControl;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080068 int mFlags;
69 IBinder mLocalWin;
Vladislav Kaznacheevc7482412015-11-05 14:03:07 -080070 int mPid;
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -070071 int mUid;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080072 ClipData mData;
73 ClipDescription mDataDescription;
74 boolean mDragResult;
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -080075 float mOriginalAlpha;
76 float mOriginalX, mOriginalY;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080077 float mCurrentX, mCurrentY;
78 float mThumbOffsetX, mThumbOffsetY;
79 InputChannel mServerChannel, mClientChannel;
Jeff Brown32cbc38552011-12-01 14:01:49 -080080 DragInputEventReceiver mInputEventReceiver;
Jeff Brownea426552011-07-18 16:53:48 -070081 InputApplicationHandle mDragApplicationHandle;
82 InputWindowHandle mDragWindowHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080083 WindowState mTargetWindow;
84 ArrayList<WindowState> mNotifiedWindows;
85 boolean mDragInProgress;
Craig Mautner39834192012-09-02 07:47:24 -070086 Display mDisplay;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080087
88 private final Region mTmpRegion = new Region();
Vladislav Kaznacheevc7ad0a02015-03-19 10:13:31 -070089 private final Rect mTmpRect = new Rect();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080090
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -080091 private Animation mAnimation;
92 final Transformation mTransformation = new Transformation();
93 private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
94
Mathias Agopian3866f0d2013-02-11 22:08:48 -080095 DragState(WindowManagerService service, IBinder token, SurfaceControl surface,
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080096 int flags, IBinder localWin) {
97 mService = service;
98 mToken = token;
Mathias Agopian29479eb2013-02-14 14:36:04 -080099 mSurfaceControl = surface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800100 mFlags = flags;
101 mLocalWin = localWin;
102 mNotifiedWindows = new ArrayList<WindowState>();
103 }
104
105 void reset() {
Mathias Agopian29479eb2013-02-14 14:36:04 -0800106 if (mSurfaceControl != null) {
107 mSurfaceControl.destroy();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800108 }
Mathias Agopian29479eb2013-02-14 14:36:04 -0800109 mSurfaceControl = null;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800110 mFlags = 0;
111 mLocalWin = null;
112 mToken = null;
113 mData = null;
114 mThumbOffsetX = mThumbOffsetY = 0;
115 mNotifiedWindows = null;
116 }
117
Craig Mautner3486b962012-08-27 11:31:24 -0700118 /**
Craig Mautner39834192012-09-02 07:47:24 -0700119 * @param display The Display that the window being dragged is on.
Craig Mautner3486b962012-08-27 11:31:24 -0700120 */
Craig Mautner39834192012-09-02 07:47:24 -0700121 void register(Display display) {
122 mDisplay = display;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800123 if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800124 if (mClientChannel != null) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800125 Slog.e(TAG_WM, "Duplicate register of drag input channel");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800126 } else {
127 InputChannel[] channels = InputChannel.openInputChannelPair("drag");
128 mServerChannel = channels[0];
129 mClientChannel = channels[1];
130 mService.mInputManager.registerInputChannel(mServerChannel, null);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800131 mInputEventReceiver = mService.new DragInputEventReceiver(mClientChannel,
132 mService.mH.getLooper());
Jeff Brownea426552011-07-18 16:53:48 -0700133
134 mDragApplicationHandle = new InputApplicationHandle(null);
135 mDragApplicationHandle.name = "drag";
136 mDragApplicationHandle.dispatchingTimeoutNanos =
137 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
138
Craig Mautner59c00972012-07-30 12:10:24 -0700139 mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
Craig Mautner39834192012-09-02 07:47:24 -0700140 mDisplay.getDisplayId());
Jeff Brownea426552011-07-18 16:53:48 -0700141 mDragWindowHandle.name = "drag";
142 mDragWindowHandle.inputChannel = mServerChannel;
143 mDragWindowHandle.layer = getDragLayerLw();
144 mDragWindowHandle.layoutParamsFlags = 0;
145 mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
146 mDragWindowHandle.dispatchingTimeoutNanos =
147 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
148 mDragWindowHandle.visible = true;
149 mDragWindowHandle.canReceiveKeys = false;
150 mDragWindowHandle.hasFocus = true;
151 mDragWindowHandle.hasWallpaper = false;
152 mDragWindowHandle.paused = false;
153 mDragWindowHandle.ownerPid = Process.myPid();
154 mDragWindowHandle.ownerUid = Process.myUid();
155 mDragWindowHandle.inputFeatures = 0;
156 mDragWindowHandle.scaleFactor = 1.0f;
157
158 // The drag window cannot receive new touches.
159 mDragWindowHandle.touchableRegion.setEmpty();
160
161 // The drag window covers the entire display
162 mDragWindowHandle.frameLeft = 0;
163 mDragWindowHandle.frameTop = 0;
Craig Mautner39834192012-09-02 07:47:24 -0700164 Point p = new Point();
165 mDisplay.getRealSize(p);
166 mDragWindowHandle.frameRight = p.x;
167 mDragWindowHandle.frameBottom = p.y;
Jeff Brown01a98dd2011-09-20 15:08:29 -0700168
169 // Pause rotations before a drag.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800170 if (DEBUG_ORIENTATION) {
171 Slog.d(TAG_WM, "Pausing rotation during drag");
Jeff Brown01a98dd2011-09-20 15:08:29 -0700172 }
173 mService.pauseRotationLocked();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800174 }
175 }
176
177 void unregister() {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800178 if (DEBUG_DRAG) Slog.d(TAG_WM, "unregistering drag input channel");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800179 if (mClientChannel == null) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800180 Slog.e(TAG_WM, "Unregister of nonexistent drag input channel");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800181 } else {
182 mService.mInputManager.unregisterInputChannel(mServerChannel);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800183 mInputEventReceiver.dispose();
184 mInputEventReceiver = null;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800185 mClientChannel.dispose();
186 mServerChannel.dispose();
187 mClientChannel = null;
188 mServerChannel = null;
Jeff Browncc4f7db2011-08-30 20:34:48 -0700189
190 mDragWindowHandle = null;
191 mDragApplicationHandle = null;
Jeff Brown01a98dd2011-09-20 15:08:29 -0700192
193 // Resume rotations after a drag.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800194 if (DEBUG_ORIENTATION) {
195 Slog.d(TAG_WM, "Resuming rotation after drag");
Jeff Brown01a98dd2011-09-20 15:08:29 -0700196 }
197 mService.resumeRotationLocked();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800198 }
199 }
200
201 int getDragLayerLw() {
202 return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
203 * WindowManagerService.TYPE_LAYER_MULTIPLIER
204 + WindowManagerService.TYPE_LAYER_OFFSET;
205 }
206
207 /* call out to each visible window/session informing it about the drag
208 */
209 void broadcastDragStartedLw(final float touchX, final float touchY) {
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800210 mOriginalX = mCurrentX = touchX;
211 mOriginalY = mCurrentY = touchY;
212
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800213 // Cache a base-class instance of the clip metadata so that parceling
214 // works correctly in calling out to the apps.
215 mDataDescription = (mData != null) ? mData.getDescription() : null;
216 mNotifiedWindows.clear();
217 mDragInProgress = true;
218
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800219 if (DEBUG_DRAG) {
220 Slog.d(TAG_WM, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800221 }
222
Craig Mautner5c0e78c2012-09-12 16:45:36 -0700223 final WindowList windows = mService.getWindowListLocked(mDisplay);
Craig Mautner2d5618c2012-10-18 13:55:47 -0700224 if (windows != null) {
225 final int N = windows.size();
226 for (int i = 0; i < N; i++) {
227 sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
228 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800229 }
230 }
231
232 /* helper - send a caller-provided event, presumed to be DRAG_STARTED, if the
233 * designated window is potentially a drop recipient. There are race situations
234 * around DRAG_ENDED broadcast, so we make sure that once we've declared that
235 * the drag has ended, we never send out another DRAG_STARTED for this drag action.
236 *
237 * This method clones the 'event' parameter if it's being delivered to the same
238 * process, so it's safe for the caller to call recycle() on the event afterwards.
239 */
240 private void sendDragStartedLw(WindowState newWin, float touchX, float touchY,
241 ClipDescription desc) {
242 // Don't actually send the event if the drag is supposed to be pinned
243 // to the originating window but 'newWin' is not that window.
244 if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
245 final IBinder winBinder = newWin.mClient.asBinder();
246 if (winBinder != mLocalWin) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800247 if (DEBUG_DRAG) {
248 Slog.d(TAG_WM, "Not dispatching local DRAG_STARTED to " + newWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800249 }
250 return;
251 }
252 }
253
254 if (mDragInProgress && newWin.isPotentialDragTarget()) {
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700255 DragEvent event = obtainDragEvent(newWin, DragEvent.ACTION_DRAG_STARTED,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700256 touchX, touchY, null, desc, null, null, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800257 try {
258 newWin.mClient.dispatchDragEvent(event);
259 // track each window that we've notified that the drag is starting
260 mNotifiedWindows.add(newWin);
261 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800262 Slog.w(TAG_WM, "Unable to drag-start window " + newWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800263 } finally {
264 // if the callee was local, the dispatch has already recycled the event
265 if (Process.myPid() != newWin.mSession.mPid) {
266 event.recycle();
267 }
268 }
269 }
270 }
271
272 /* helper - construct and send a DRAG_STARTED event only if the window has not
273 * previously been notified, i.e. it became visible after the drag operation
274 * was begun. This is a rare case.
275 */
276 void sendDragStartedIfNeededLw(WindowState newWin) {
277 if (mDragInProgress) {
278 // If we have sent the drag-started, we needn't do so again
279 for (WindowState ws : mNotifiedWindows) {
280 if (ws == newWin) {
281 return;
282 }
283 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800284 if (DEBUG_DRAG) {
285 Slog.d(TAG_WM, "need to send DRAG_STARTED to new window " + newWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800286 }
287 sendDragStartedLw(newWin, mCurrentX, mCurrentY, mDataDescription);
288 }
289 }
290
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800291 private void broadcastDragEndedLw() {
Vladislav Kaznacheev68dd2e82015-10-22 17:06:40 -0700292 final int myPid = Process.myPid();
293
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800294 if (DEBUG_DRAG) {
295 Slog.d(TAG_WM, "broadcasting DRAG_ENDED");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800296 }
Vladislav Kaznacheev68dd2e82015-10-22 17:06:40 -0700297 for (WindowState ws : mNotifiedWindows) {
Vladislav Kaznacheevc7482412015-11-05 14:03:07 -0800298 float x = 0;
299 float y = 0;
300 if (!mDragResult && (ws.mSession.mPid == mPid)) {
301 // Report unconsumed drop location back to the app that started the drag.
302 x = mCurrentX;
303 y = mCurrentY;
304 }
Vladislav Kaznacheev68dd2e82015-10-22 17:06:40 -0700305 DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
Vladislav Kaznacheevc7482412015-11-05 14:03:07 -0800306 x, y, null, null, null, null, mDragResult);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800307 try {
308 ws.mClient.dispatchDragEvent(evt);
309 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800310 Slog.w(TAG_WM, "Unable to drag-end window " + ws);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800311 }
Vladislav Kaznacheev68dd2e82015-10-22 17:06:40 -0700312 // if the current window is in the same process,
313 // the dispatch has already recycled the event
314 if (myPid != ws.mSession.mPid) {
315 evt.recycle();
316 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800317 }
318 mNotifiedWindows.clear();
319 mDragInProgress = false;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800320 }
321
322 void endDragLw() {
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800323 if (mAnimation != null) {
324 return;
325 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800326 if (!mDragResult) {
327 mAnimation = createReturnAnimationLocked();
328 mService.scheduleAnimationLocked();
329 return; // Will call cleanUpDragLw when the animation is done.
330 }
331 cleanUpDragLw();
332 }
333
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800334 void cancelDragLw() {
335 if (mAnimation != null) {
336 return;
337 }
338 mAnimation = createCancelAnimationLocked();
339 mService.scheduleAnimationLocked();
340 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800341
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800342 private void cleanUpDragLw() {
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800343 broadcastDragEndedLw();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800344
345 // stop intercepting input
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800346 unregister();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800347
348 // free our resources and drop all the object references
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800349 reset();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800350 mService.mDragState = null;
Chong Zhang8e89b312015-09-09 15:09:30 -0700351
352 mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800353 }
354
355 void notifyMoveLw(float x, float y) {
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800356 if (mAnimation != null) {
357 return;
358 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800359 mCurrentX = x;
360 mCurrentY = y;
361
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800362 final int myPid = Process.myPid();
363
364 // Move the surface to the given touch
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800365 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
366 TAG_WM, ">>> OPEN TRANSACTION notifyMoveLw");
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800367 SurfaceControl.openTransaction();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800368 try {
Mathias Agopian29479eb2013-02-14 14:36:04 -0800369 mSurfaceControl.setPosition(x - mThumbOffsetX, y - mThumbOffsetY);
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800370 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG "
Mathias Agopian29479eb2013-02-14 14:36:04 -0800371 + mSurfaceControl + ": pos=(" +
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800372 (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
373 } finally {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800374 SurfaceControl.closeTransaction();
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800375 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
376 TAG_WM, "<<< CLOSE TRANSACTION notifyMoveLw");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800377 }
378
379 // Tell the affected window
380 WindowState touchedWin = getTouchedWinAtPointLw(x, y);
381 if (touchedWin == null) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800382 if (DEBUG_DRAG) Slog.d(TAG_WM, "No touched win at x=" + x + " y=" + y);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800383 return;
384 }
385 if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
386 final IBinder touchedBinder = touchedWin.mClient.asBinder();
387 if (touchedBinder != mLocalWin) {
388 // This drag is pinned only to the originating window, but the drag
389 // point is outside that window. Pretend it's over empty space.
390 touchedWin = null;
391 }
392 }
393 try {
394 // have we dragged over a new window?
395 if ((touchedWin != mTargetWindow) && (mTargetWindow != null)) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800396 if (DEBUG_DRAG) {
397 Slog.d(TAG_WM, "sending DRAG_EXITED to " + mTargetWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800398 }
399 // force DRAG_EXITED_EVENT if appropriate
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700400 DragEvent evt = obtainDragEvent(mTargetWindow, DragEvent.ACTION_DRAG_EXITED,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700401 x, y, null, null, null, null, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800402 mTargetWindow.mClient.dispatchDragEvent(evt);
403 if (myPid != mTargetWindow.mSession.mPid) {
404 evt.recycle();
405 }
406 }
407 if (touchedWin != null) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800408 if (false && DEBUG_DRAG) {
409 Slog.d(TAG_WM, "sending DRAG_LOCATION to " + touchedWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800410 }
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700411 DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DRAG_LOCATION,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700412 x, y, null, null, null, null, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800413 touchedWin.mClient.dispatchDragEvent(evt);
414 if (myPid != touchedWin.mSession.mPid) {
415 evt.recycle();
416 }
417 }
418 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800419 Slog.w(TAG_WM, "can't send drag notification to windows");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800420 }
421 mTargetWindow = touchedWin;
422 }
423
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700424 WindowState getDropTargetWinLw(float x, float y) {
425 return getTouchedWinAtPointLw(x, y);
426 }
427
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800428 // Tell the drop target about the data. Returns 'true' if we can immediately
429 // dispatch the global drag-ended message, 'false' if we need to wait for a
430 // result from the recipient.
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700431 boolean notifyDropLw(WindowState touchedWin, DropPermissionHolder dropPermissionHolder,
432 float x, float y) {
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800433 if (mAnimation != null) {
434 return false;
435 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800436 mCurrentX = x;
437 mCurrentY = y;
438
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800439 if (touchedWin == null) {
440 // "drop" outside a valid window -- no recipient to apply a
441 // timeout to, and we can send the drag-ended message immediately.
442 mDragResult = false;
443 return true;
444 }
445
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800446 if (DEBUG_DRAG) {
447 Slog.d(TAG_WM, "sending DROP to " + touchedWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800448 }
449 final int myPid = Process.myPid();
450 final IBinder token = touchedWin.mClient.asBinder();
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700451 DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DROP, x, y,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700452 null, null, mData, dropPermissionHolder, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800453 try {
454 touchedWin.mClient.dispatchDragEvent(evt);
455
456 // 5 second timeout for this window to respond to the drop
457 mService.mH.removeMessages(H.DRAG_END_TIMEOUT, token);
458 Message msg = mService.mH.obtainMessage(H.DRAG_END_TIMEOUT, token);
459 mService.mH.sendMessageDelayed(msg, 5000);
460 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800461 Slog.w(TAG_WM, "can't send drop notification to win " + touchedWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800462 return true;
463 } finally {
464 if (myPid != touchedWin.mSession.mPid) {
465 evt.recycle();
466 }
467 }
468 mToken = token;
469 return false;
470 }
471
472 // Find the visible, touch-deliverable window under the given point
473 private WindowState getTouchedWinAtPointLw(float xf, float yf) {
474 WindowState touchedWin = null;
475 final int x = (int) xf;
476 final int y = (int) yf;
Craig Mautner59c00972012-07-30 12:10:24 -0700477
Craig Mautner5c0e78c2012-09-12 16:45:36 -0700478 final WindowList windows = mService.getWindowListLocked(mDisplay);
Craig Mautner2d5618c2012-10-18 13:55:47 -0700479 if (windows == null) {
480 return null;
481 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800482 final int N = windows.size();
483 for (int i = N - 1; i >= 0; i--) {
484 WindowState child = windows.get(i);
485 final int flags = child.mAttrs.flags;
486 if (!child.isVisibleLw()) {
487 // not visible == don't tell about drags
488 continue;
489 }
490 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
491 // not touchable == don't tell about drags
492 continue;
493 }
494
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800495 child.getVisibleBounds(mTmpRect);
Vladislav Kaznacheevc7ad0a02015-03-19 10:13:31 -0700496 if (!mTmpRect.contains(x, y)) {
497 // outside of this window's activity stack == don't tell about drags
498 continue;
499 }
500
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800501 child.getTouchableRegion(mTmpRegion);
502
503 final int touchFlags = flags &
504 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
505 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
506 if (mTmpRegion.contains(x, y) || touchFlags == 0) {
507 // Found it
508 touchedWin = child;
509 break;
510 }
511 }
512
513 return touchedWin;
514 }
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700515
516 private static DragEvent obtainDragEvent(WindowState win, int action,
517 float x, float y, Object localState,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700518 ClipDescription description, ClipData data,
519 DropPermissionHolder dropPermissionHolder,
520 boolean result) {
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700521 float winX = x - win.mFrame.left;
522 float winY = y - win.mFrame.top;
523 if (win.mEnforceSizeCompat) {
524 winX *= win.mGlobalScale;
525 winY *= win.mGlobalScale;
526 }
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700527 return DragEvent.obtain(action, winX, winY, localState, description, data,
528 dropPermissionHolder, result);
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700529 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800530
531 boolean stepAnimationLocked(long currentTimeMs) {
532 if (mAnimation == null) {
533 return false;
534 }
535
536 mTransformation.clear();
537 if (!mAnimation.getTransformation(currentTimeMs, mTransformation)) {
538 cleanUpDragLw();
539 return false;
540 }
541
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800542 mTransformation.getMatrix().postTranslate(
543 mCurrentX - mThumbOffsetX, mCurrentY - mThumbOffsetY);
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800544 final float tmpFloats[] = mService.mTmpFloats;
545 mTransformation.getMatrix().getValues(tmpFloats);
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800546 mSurfaceControl.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800547 mSurfaceControl.setAlpha(mTransformation.getAlpha());
548 mSurfaceControl.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
549 tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
550 return true;
551 }
552
553 private Animation createReturnAnimationLocked() {
554 final AnimationSet set = new AnimationSet(false);
555 set.addAnimation(new TranslateAnimation(
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800556 0, mOriginalX - mCurrentX, 0, mOriginalY - mCurrentY));
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800557 set.addAnimation(new AlphaAnimation(mOriginalAlpha, mOriginalAlpha / 2));
558 set.setDuration(ANIMATION_DURATION_MS);
559 set.setInterpolator(mCubicEaseOutInterpolator);
560 set.initialize(0, 0, 0, 0);
561 set.start(); // Will start on the first call to getTransformation.
562 return set;
563 }
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800564
565 private Animation createCancelAnimationLocked() {
566 final AnimationSet set = new AnimationSet(false);
567 set.addAnimation(new ScaleAnimation(1, 0, 1, 0, mThumbOffsetX, mThumbOffsetY));
568 set.addAnimation(new AlphaAnimation(mOriginalAlpha, 0));
569 set.setDuration(ANIMATION_DURATION_MS);
570 set.setInterpolator(mCubicEaseOutInterpolator);
571 set.initialize(0, 0, 0, 0);
572 set.start(); // Will start on the first call to getTransformation.
573 return set;
574 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800575}