diff options
| author | 2016-11-03 17:48:09 +0000 | |
|---|---|---|
| committer | 2016-11-03 17:48:12 +0000 | |
| commit | 34f47747f7b0916f42ba9ffb25f1b4f21dce6d35 (patch) | |
| tree | 5f9889817b51cc193f14da539d5b093f0d3393f0 | |
| parent | 609f164295e6734118ef9aca2669d157167cfb8d (diff) | |
| parent | dff5c08bfd5c15f11b71ce953282ed519ff1b290 (diff) | |
Merge changes I0d6f2f0c,I278ab8c3
* changes:
Experiment for snapping PIP to closest edge.
Experiment with allowing tap to break through to interact with the PIP.
12 files changed, 483 insertions, 17 deletions
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl index 830591d5b503..a81eef831f4e 100644 --- a/core/java/android/view/IPinnedStackController.aidl +++ b/core/java/android/view/IPinnedStackController.aidl @@ -30,4 +30,9 @@ interface IPinnedStackController { * Notifies the controller that the user is currently interacting with the PIP. */ oneway void setInInteractiveMode(boolean inInteractiveMode); + + /** + * Notifies the controller that the desired snap mode is to the closest edge. + */ + oneway void setSnapToEdge(boolean snapToEdge); } diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java index 45b7b0183fd8..cbacf269a0f0 100644 --- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java +++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java @@ -46,7 +46,8 @@ public class PipSnapAlgorithm { private final Context mContext; private final ArrayList<Integer> mSnapGravities = new ArrayList<>(); - private final int mSnapMode = SNAP_MODE_CORNERS_ONLY; + private final int mDefaultSnapMode = SNAP_MODE_CORNERS_ONLY; + private int mSnapMode = mDefaultSnapMode; private Scroller mScroller; private int mOrientation = Configuration.ORIENTATION_UNDEFINED; @@ -65,6 +66,13 @@ public class PipSnapAlgorithm { } /** + * Enables snapping to the closest edge. + */ + public void setSnapToEdge(boolean snapToEdge) { + mSnapMode = snapToEdge ? SNAP_MODE_EDGE : mDefaultSnapMode; + } + + /** * @return the closest absolute snap stack bounds for the given {@param stackBounds} moving at * the given {@param velocityX} and {@param velocityY}. The {@param movementBounds} should be * those for the given {@param stackBounds}. diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 4d59d574adc8..2adb26159622 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -415,6 +415,18 @@ android:launchMode="singleTop" android:excludeFromRecents="true" /> + <activity + android:name=".pip.phone.PipMenuActivity" + android:theme="@style/PipPhoneOverlayControlTheme" + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" + android:excludeFromRecents="true" + android:exported="false" + android:resizeableActivity="true" + android:supportsPictureInPicture="true" + android:stateNotNeeded="true" + android:taskAffinity="" + androidprv:alwaysFocusable="true" /> + <!-- platform logo easter egg activity --> <activity android:name=".DessertCase" diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml new file mode 100644 index 000000000000..88e6e725c976 --- /dev/null +++ b/packages/SystemUI/res/layout/pip_menu_activity.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#33000000"> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center"> + <Button + android:id="@+id/expand_pip" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:textSize="14sp" + android:textColor="#ffffffff" + android:text="@string/pip_phone_expand" + android:fontFamily="sans-serif" /> + </LinearLayout> +</FrameLayout> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index d8c8b82eee4a..37a7e38eb4f9 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1675,6 +1675,9 @@ not appear on production builds ever. --> <string name="tuner_doze_always_on" translatable="false">Always on</string> + <!-- Making the PIP fullscreen --> + <string name="pip_phone_expand">Expand</string> + <!-- PIP section of the tuner. Non-translatable since it should not appear on production builds ever. --> <string name="picture_in_picture" translatable="false">Picture-in-Picture</string> @@ -1695,4 +1698,20 @@ not appear on production builds ever. --> <string name="pip_drag_to_dismiss_summary" translatable="false">Drag to the dismiss target at the bottom of the screen to close the PIP</string> + <!-- PIP tap once to break through to the activity. Non-translatable since it should + not appear on production builds ever. --> + <string name="pip_tap_through_title" translatable="false">Tap to interact</string> + + <!-- PIP tap once to break through to the activity. Non-translatable since it should + not appear on production builds ever. --> + <string name="pip_tap_through_summary" translatable="false">Tap once to interact with the activity</string> + + <!-- PIP snap to closest edge. Non-translatable since it should + not appear on production builds ever. --> + <string name="pip_snap_mode_edge_title" translatable="false">Snap to closest edge</string> + + <!-- PIP snap to closest edge. Non-translatable since it should + not appear on production builds ever. --> + <string name="pip_snap_mode_edge_summary" translatable="false">Snap to the closest edge</string> + </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index e5bc8b996cea..6661f076d848 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -56,6 +56,24 @@ <item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item> </style> + <style name="PipPhoneOverlayControlTheme" parent="@android:style/Theme.Material"> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowNoTitle">true</item> + <item name="android:windowContentOverlay">@null</item> + <item name="android:windowBackground">@drawable/forced_resizable_background</item> + <item name="android:colorBackgroundCacheHint">@null</item> + <item name="android:statusBarColor">@color/transparent</item> + <item name="android:windowAnimationStyle">@style/Animation.PipPhoneOverlayControl</item> + </style> + + <style name="Animation.PipPhoneOverlayControl" parent="@android:style/Animation"> + <item name="android:activityOpenEnterAnimation">@anim/forced_resizable_enter</item> + + <!-- If the target stack doesn't have focus, we do a task to front animation. --> + <item name="android:taskToFrontEnterAnimation">@anim/forced_resizable_enter</item> + <item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item> + </style> + <style name="TextAppearance.StatusBar.HeadsUp" parent="@*android:style/TextAppearance.StatusBar"> </style> diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml index 942f8472b7ef..f09d6e9fe052 100644 --- a/packages/SystemUI/res/xml/tuner_prefs.xml +++ b/packages/SystemUI/res/xml/tuner_prefs.xml @@ -137,6 +137,18 @@ android:summary="@string/pip_drag_to_dismiss_summary" sysui:defValue="true" /> + <com.android.systemui.tuner.TunerSwitch + android:key="pip_tap_through" + android:title="@string/pip_tap_through_title" + android:summary="@string/pip_tap_through_summary" + sysui:defValue="false" /> + + <com.android.systemui.tuner.TunerSwitch + android:key="pip_snap_mode_edge" + android:title="@string/pip_snap_mode_edge_title" + android:summary="@string/pip_snap_mode_edge_summary" + sysui:defValue="false" /> + </PreferenceScreen> <PreferenceScreen diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index f9a4f7ced6cc..7b8d27eef8b4 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -34,6 +34,7 @@ public class PipManager { private IActivityManager mActivityManager; private IWindowManager mWindowManager; + private PipMenuActivityController mMenuController; private PipTouchHandler mTouchHandler; private PipManager() {} @@ -46,7 +47,9 @@ public class PipManager { mActivityManager = ActivityManagerNative.getDefault(); mWindowManager = WindowManagerGlobal.getWindowManagerService(); - mTouchHandler = new PipTouchHandler(context, mActivityManager, mWindowManager); + mMenuController = new PipMenuActivityController(context, mActivityManager, mWindowManager); + mTouchHandler = new PipTouchHandler(context, mMenuController, mActivityManager, + mWindowManager); } /** diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java new file mode 100644 index 000000000000..bfe5cff90a24 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.pip.phone; + +import android.annotation.Nullable; +import android.app.Activity; +import android.app.ActivityManager; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.util.Log; +import android.view.View; +import com.android.systemui.R; + +/** + * Translucent activity that gets started on top of a task in PIP to allow the user to control it. + */ +public class PipMenuActivity extends Activity { + + private static final String TAG = "PipMenuActivity"; + + public static final int MESSAGE_FINISH_SELF = 2; + + private static final long INITIAL_DISMISS_DELAY = 2000; + private static final long POST_INTERACTION_DISMISS_DELAY = 1500; + + private Messenger mToControllerMessenger; + private Messenger mMessenger = new Messenger(new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_FINISH_SELF: + finish(); + break; + } + } + }); + + private final Runnable mFinishRunnable = new Runnable() { + @Override + public void run() { + finish(); + } + }; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent startingIntet = getIntent(); + mToControllerMessenger = startingIntet.getParcelableExtra( + PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER); + + setContentView(R.layout.pip_menu_activity); + findViewById(R.id.expand_pip).setOnClickListener((view) -> { + finish(); + notifyExpandPip(); + }); + } + + @Override + protected void onStart() { + super.onStart(); + notifyActivityVisibility(true); + repostDelayedFinish(INITIAL_DISMISS_DELAY); + } + + @Override + public void onUserInteraction() { + repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY); + } + + @Override + protected void onStop() { + super.onStop(); + finish(); + } + + @Override + public void finish() { + View v = getWindow().getDecorView(); + v.removeCallbacks(mFinishRunnable); + notifyActivityVisibility(false); + super.finish(); + overridePendingTransition(0, R.anim.forced_resizable_exit); + } + + @Override + public void setTaskDescription(ActivityManager.TaskDescription taskDescription) { + // Do nothing + } + + private void notifyActivityVisibility(boolean visible) { + Message m = Message.obtain(); + m.what = PipMenuActivityController.MESSAGE_ACTIVITY_VISIBILITY_CHANGED; + m.arg1 = visible ? 1 : 0; + m.replyTo = visible ? mMessenger : null; + try { + mToControllerMessenger.send(m); + } catch (RemoteException e) { + Log.e(TAG, "Could not notify controller of PIP menu visibility", e); + } + } + + private void notifyExpandPip() { + Message m = Message.obtain(); + m.what = PipMenuActivityController.MESSAGE_EXPAND_PIP; + try { + mToControllerMessenger.send(m); + } catch (RemoteException e) { + Log.e(TAG, "Could not notify controller to expand PIP", e); + } + } + + private void repostDelayedFinish(long delay) { + View v = getWindow().getDecorView(); + v.removeCallbacks(mFinishRunnable); + v.postDelayed(mFinishRunnable, delay); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java new file mode 100644 index 000000000000..d1bce0c74ccd --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java @@ -0,0 +1,126 @@ +package com.android.systemui.pip.phone; + +import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import static android.view.WindowManager.INPUT_CONSUMER_PIP; + +import android.app.ActivityManager.StackInfo; +import android.app.ActivityOptions; +import android.app.IActivityManager; +import android.content.Context; +import android.content.Intent; +import android.graphics.Rect; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Log; +import android.view.IWindowManager; + +import java.util.ArrayList; + +public class PipMenuActivityController { + + private static final String TAG = "PipMenuActivityController"; + + public static final String EXTRA_CONTROLLER_MESSENGER = "messenger"; + public static final int MESSAGE_ACTIVITY_VISIBILITY_CHANGED = 1; + public static final int MESSAGE_EXPAND_PIP = 3; + + /** + * A listener interface to receive notification on changes in PIP. + */ + public interface Listener { + /** + * Called when the PIP menu visibility changes. + */ + void onPipMenuVisibilityChanged(boolean visible); + } + + private Context mContext; + private IActivityManager mActivityManager; + private IWindowManager mWindowManager; + private ArrayList<Listener> mListeners = new ArrayList<>(); + + private Messenger mToActivityMessenger; + private Messenger mMessenger = new Messenger(new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_ACTIVITY_VISIBILITY_CHANGED: { + boolean visible = msg.arg1 > 0; + int listenerCount = mListeners.size(); + for (int i = 0; i < listenerCount; i++) { + mListeners.get(i).onPipMenuVisibilityChanged(visible); + } + mToActivityMessenger = msg.replyTo; + break; + } + case MESSAGE_EXPAND_PIP: { + try { + mActivityManager.resizeStack(PINNED_STACK_ID, null, true, true, true, 225); + } catch (RemoteException e) { + Log.e(TAG, "Error showing PIP menu activity", e); + } + break; + } + } + } + }); + + public PipMenuActivityController(Context context, IActivityManager activityManager, + IWindowManager windowManager) { + mContext = context; + mActivityManager = activityManager; + mWindowManager = windowManager; + } + + /** + * Adds a new menu activity listener. + */ + public void addListener(Listener listener) { + if (!mListeners.contains(listener)) { + mListeners.add(listener); + } + } + + /** + * Shows the menu activity. + */ + public void showMenu() { + // Start the menu activity on the top task of the pinned stack + try { + StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID); + if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null && + pinnedStackInfo.taskIds.length > 0) { + Intent intent = new Intent(mContext, PipMenuActivity.class); + intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger); + ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchTaskId( + pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]); + options.setTaskOverlay(true); + mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT); + } else { + Log.e(TAG, "No PIP tasks found"); + } + } catch (RemoteException e) { + Log.e(TAG, "Error showing PIP menu activity", e); + } + } + + /** + * Hides the menu activity. + */ + public void hideMenu() { + if (mToActivityMessenger != null) { + Message m = Message.obtain(); + m.what = PipMenuActivity.MESSAGE_FINISH_SELF; + try { + mToActivityMessenger.send(m); + } catch (RemoteException e) { + Log.e(TAG, "Could not notify menu activity to finish", e); + } + mToActivityMessenger = null; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index e32022abdf38..a3593806fb1f 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -32,6 +32,7 @@ import android.app.IActivityManager; import android.content.Context; import android.graphics.PointF; import android.graphics.Rect; +import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.util.Log; @@ -61,6 +62,8 @@ public class PipTouchHandler implements TunerService.Tunable { private static final String TUNER_KEY_SWIPE_TO_DISMISS = "pip_swipe_to_dismiss"; private static final String TUNER_KEY_DRAG_TO_DISMISS = "pip_drag_to_dismiss"; + private static final String TUNER_KEY_TAP_THROUGH = "pip_tap_through"; + private static final String TUNER_KEY_SNAP_MODE_EDGE = "pip_snap_mode_edge"; private static final int SNAP_STACK_DURATION = 225; private static final int DISMISS_STACK_DURATION = 375; @@ -70,17 +73,20 @@ public class PipTouchHandler implements TunerService.Tunable { private final IActivityManager mActivityManager; private final IWindowManager mWindowManager; private final ViewConfiguration mViewConfig; - private final InputChannel mInputChannel = new InputChannel(); private final PinnedStackListener mPinnedStackListener = new PinnedStackListener(); + private final PipMenuListener mMenuListener = new PipMenuListener(); private IPinnedStackController mPinnedStackController; - private final PipInputEventReceiver mInputEventReceiver; + private PipInputEventReceiver mInputEventReceiver; + private PipMenuActivityController mMenuController; private PipDismissViewController mDismissViewController; private final PipSnapAlgorithm mSnapAlgorithm; private PipMotionHelper mMotionHelper; private boolean mEnableSwipeToDismiss = true; private boolean mEnableDragToDismiss = true; + private boolean mEnableTapThrough = false; + private boolean mEnableSnapToEdge = false; private final Rect mPinnedStackBounds = new Rect(); private final Rect mBoundedPinnedStackBounds = new Rect(); @@ -97,6 +103,7 @@ public class PipTouchHandler implements TunerService.Tunable { private final PointF mLastTouch = new PointF(); private boolean mIsDragging; private boolean mIsSwipingToDismiss; + private boolean mIsTappingThrough; private int mActivePointerId; private final FlingAnimationUtils mFlingAnimationUtils; @@ -120,7 +127,7 @@ public class PipTouchHandler implements TunerService.Tunable { // To be implemented for input handling over Pip windows if (event instanceof MotionEvent) { MotionEvent ev = (MotionEvent) event; - handleTouchEvent(ev); + handled = handleTouchEvent(ev); } } finally { finishInputEvent(event, handled); @@ -144,13 +151,26 @@ public class PipTouchHandler implements TunerService.Tunable { } } - public PipTouchHandler(Context context, IActivityManager activityManager, - IWindowManager windowManager) { + /** + * A listener for the PIP menu activity. + */ + private class PipMenuListener implements PipMenuActivityController.Listener { + @Override + public void onPipMenuVisibilityChanged(boolean visible) { + if (!visible) { + mIsTappingThrough = false; + registerInputConsumer(); + } else { + unregisterInputConsumer(); + } + } + } + + public PipTouchHandler(Context context, PipMenuActivityController menuController, + IActivityManager activityManager, IWindowManager windowManager) { // Initialize the Pip input consumer try { - windowManager.destroyInputConsumer(INPUT_CONSUMER_PIP); - windowManager.createInputConsumer(INPUT_CONSUMER_PIP, mInputChannel); windowManager.registerPinnedStackListener(DEFAULT_DISPLAY, mPinnedStackListener); } catch (RemoteException e) { Log.e(TAG, "Failed to create PIP input consumer", e); @@ -159,22 +179,29 @@ public class PipTouchHandler implements TunerService.Tunable { mActivityManager = activityManager; mWindowManager = windowManager; mViewConfig = ViewConfiguration.get(context); - mInputEventReceiver = new PipInputEventReceiver(mInputChannel, Looper.myLooper()); - if (mEnableDragToDismiss) { - mDismissViewController = new PipDismissViewController(context); - } + mMenuController = menuController; + mMenuController.addListener(mMenuListener); + mDismissViewController = new PipDismissViewController(context); mSnapAlgorithm = new PipSnapAlgorithm(mContext); mFlingAnimationUtils = new FlingAnimationUtils(context, 2f); mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler()); + registerInputConsumer(); // Register any tuner settings changes TunerService.get(context).addTunable(this, TUNER_KEY_SWIPE_TO_DISMISS, - TUNER_KEY_DRAG_TO_DISMISS); + TUNER_KEY_DRAG_TO_DISMISS, TUNER_KEY_TAP_THROUGH, TUNER_KEY_SNAP_MODE_EDGE); } @Override public void onTuningChanged(String key, String newValue) { if (newValue == null) { + // Reset back to default + mEnableSwipeToDismiss = true; + mEnableDragToDismiss = true; + mEnableTapThrough = false; + mIsTappingThrough = false; + mEnableSnapToEdge = false; + setSnapToEdge(false); return; } switch (key) { @@ -184,6 +211,14 @@ public class PipTouchHandler implements TunerService.Tunable { case TUNER_KEY_DRAG_TO_DISMISS: mEnableDragToDismiss = Integer.parseInt(newValue) != 0; break; + case TUNER_KEY_TAP_THROUGH: + mEnableTapThrough = Integer.parseInt(newValue) != 0; + mIsTappingThrough = false; + break; + case TUNER_KEY_SNAP_MODE_EDGE: + mEnableSnapToEdge = Integer.parseInt(newValue) != 0; + setSnapToEdge(mEnableSnapToEdge); + break; } } @@ -192,10 +227,10 @@ public class PipTouchHandler implements TunerService.Tunable { updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */); } - private void handleTouchEvent(MotionEvent ev) { + private boolean handleTouchEvent(MotionEvent ev) { // Skip touch handling until we are bound to the controller if (mPinnedStackController == null) { - return; + return true; } switch (ev.getAction()) { @@ -239,6 +274,8 @@ public class PipTouchHandler implements TunerService.Tunable { float movement = PointF.length(mDownTouch.x - x, mDownTouch.y - y); if (movement > mViewConfig.getScaledTouchSlop()) { mIsDragging = true; + mIsTappingThrough = false; + mMenuController.hideMenu(); if (mEnableSwipeToDismiss) { // TODO: this check can have some buffer so that we only start swiping // after a significant move out of bounds @@ -328,7 +365,14 @@ public class PipTouchHandler implements TunerService.Tunable { } } } else { - expandPinnedStackToFullscreen(); + if (mEnableTapThrough) { + if (!mIsTappingThrough) { + mMenuController.showMenu(); + mIsTappingThrough = true; + } + } else { + expandPinnedStackToFullscreen(); + } } if (mEnableDragToDismiss) { mDismissViewController.destroyDismissTarget(); @@ -348,6 +392,7 @@ public class PipTouchHandler implements TunerService.Tunable { break; } } + return !mIsTappingThrough; } private void initOrResetVelocityTracker() { @@ -366,6 +411,44 @@ public class PipTouchHandler implements TunerService.Tunable { } /** + * Registers the input consumer. + */ + private void registerInputConsumer() { + final InputChannel inputChannel = new InputChannel(); + try { + mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP); + mWindowManager.createInputConsumer(INPUT_CONSUMER_PIP, inputChannel); + } catch (RemoteException e) { + Log.e(TAG, "Failed to create PIP input consumer", e); + } + mInputEventReceiver = new PipInputEventReceiver(inputChannel, Looper.myLooper()); + } + + /** + * Unregisters the input consumer. + */ + private void unregisterInputConsumer() { + try { + mWindowManager.destroyInputConsumer(INPUT_CONSUMER_PIP); + } catch (RemoteException e) { + Log.e(TAG, "Failed to destroy PIP input consumer", e); + } + mInputEventReceiver.dispose(); + } + + /** + * Sets the snap-to-edge state. + */ + private void setSnapToEdge(boolean snapToEdge) { + mSnapAlgorithm.setSnapToEdge(snapToEdge); + try { + mPinnedStackController.setSnapToEdge(snapToEdge); + } catch (RemoteException e) { + Log.e(TAG, "Could not set snap mode to edge", e); + } + } + + /** * Flings the PIP to the closest snap target. */ private void flingToSnapTarget(float velocity, float velocityX, float velocityY) { diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index faca8db3ab87..1ccf7229cc87 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -99,6 +99,13 @@ class PinnedStackController { mInInteractiveMode = inInteractiveMode; }); } + + @Override + public void setSnapToEdge(final boolean snapToEdge) { + mHandler.post(() -> { + mSnapAlgorithm.setSnapToEdge(snapToEdge); + }); + } } /** |