diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml index 43bf0ea966..52475dfc8a 100644 --- a/quickstep/res/layout/gesture_tutorial_fragment.xml +++ b/quickstep/res/layout/gesture_tutorial_fragment.xml @@ -13,7 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> - @@ -93,11 +94,11 @@ style="@style/TextAppearance.GestureTutorial.Feedback" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_above="@id/gesture_tutorial_fragment_action_button" + android:layout_below="@id/gesture_tutorial_fragment_titles_container" android:layout_centerHorizontal="true" android:layout_marginStart="@dimen/gesture_tutorial_feedback_margin_start_end" android:layout_marginEnd="@dimen/gesture_tutorial_feedback_margin_start_end" - android:layout_marginBottom="10dp"/> + android:layout_marginTop="40dp"/> @@ -126,4 +127,4 @@ android:background="@null" android:foreground="?android:attr/selectableItemBackgroundBorderless" android:stateListAnimator="@null"/> - \ No newline at end of file + \ No newline at end of file diff --git a/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java index e4b348e51b..9489bac266 100644 --- a/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java +++ b/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java @@ -143,6 +143,10 @@ public class EdgeBackGestureHandler implements OnTouchListener { return false; } + boolean onInterceptTouch(MotionEvent motionEvent) { + return isWithinTouchRegion((int) motionEvent.getX(), (int) motionEvent.getY()); + } + private boolean isWithinTouchRegion(int x, int y) { // Disallow if too far from the edge if (x > mEdgeWidth + mLeftInset && x < (mDisplaySize.x - mEdgeWidth - mRightInset)) { diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java index f897ecc01a..d1b0a7088f 100644 --- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java +++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java @@ -250,6 +250,12 @@ public class NavBarGestureHandler implements OnTouchListener, return intercepted; } + boolean onInterceptTouch(MotionEvent event) { + return mAssistantLeftRegion.contains(event.getX(), event.getY()) + || mAssistantRightRegion.contains(event.getX(), event.getY()) + || event.getY() >= mDisplaySize.y - mBottomGestureHeight; + } + protected void onMotionPauseDetected() { VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC); } diff --git a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java new file mode 100644 index 0000000000..db1afc2012 --- /dev/null +++ b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 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.quickstep.interaction; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.RelativeLayout; + +import androidx.fragment.app.FragmentManager; + +/** Root layout that TutorialFragment uses to intercept motion events. */ +public class RootSandboxLayout extends RelativeLayout { + public RootSandboxLayout(Context context) { + super(context); + } + + public RootSandboxLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public RootSandboxLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent motionEvent) { + return ((TutorialFragment) FragmentManager.findFragment(this)) + .onInterceptTouch(motionEvent); + } +} diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java b/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java new file mode 100644 index 0000000000..80ffe6609e --- /dev/null +++ b/quickstep/src/com/android/quickstep/interaction/SandboxLauncherRenderer.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 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.quickstep.interaction; + +import android.content.Context; +import android.view.View; + +import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.graphics.LauncherPreviewRenderer; + +/** Renders a fake Launcher for use in the Sandbox. */ +class SandboxLauncherRenderer extends LauncherPreviewRenderer { + SandboxLauncherRenderer(Context context, InvariantDeviceProfile idp, boolean migrated) { + super(context, idp, migrated); + } + + @Override + public boolean shouldShowRealLauncherPreview() { + return false; + } + + @Override + public boolean shouldShowQsb() { + return false; + } + + @Override + public View.OnLongClickListener getWorkspaceChildOnLongClickListener() { + return null; + } +} diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java index 73f1f8cb8c..db80342673 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java @@ -47,6 +47,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, final TextView mTitleTextView; final TextView mSubtitleTextView; final TextView mFeedbackView; + final View mLauncherView; final ClipIconView mFakeIconView; final View mFakeTaskView; final View mRippleView; @@ -68,6 +69,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, mTitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_title_view); mSubtitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_subtitle_view); mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view); + mLauncherView = tutorialFragment.getLauncherView(); mFakeIconView = rootView.findViewById(R.id.gesture_tutorial_fake_icon_view); mFakeTaskView = rootView.findViewById(R.id.gesture_tutorial_fake_task_view); mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view); @@ -162,8 +164,10 @@ abstract class TutorialController implements BackGestureAttemptCallback, if (isComplete()) { hideHandCoachingAnimation(); + mLauncherView.setVisibility(View.INVISIBLE); } else { showHandCoachingAnimation(); + mLauncherView.setVisibility(View.VISIBLE); } } diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java index 9a8264d098..c90ad94b8c 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java @@ -31,6 +31,7 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; +import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.R; import com.android.quickstep.interaction.TutorialController.TutorialType; @@ -45,6 +46,7 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { TutorialHandAnimation mHandCoachingAnimation; EdgeBackGestureHandler mEdgeBackGestureHandler; NavBarGestureHandler mNavBarGestureHandler; + private View mLauncherView; public static TutorialFragment newInstance(TutorialType tutorialType) { TutorialFragment fragment = getFragmentForTutorialType(tutorialType); @@ -114,8 +116,11 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { return insets; }); mRootView.setOnTouchListener(this); - mHandCoachingAnimation = new TutorialHandAnimation(getContext(), mRootView, - getHandAnimationResId()); + mHandCoachingAnimation = + new TutorialHandAnimation(getContext(), mRootView, getHandAnimationResId()); + InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(getContext()); + mLauncherView = new SandboxLauncherRenderer(getContext(), dp, true).getRenderedView(); + ((ViewGroup) mRootView).addView(mLauncherView, 0); return mRootView; } @@ -133,11 +138,17 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { @Override public boolean onTouch(View view, MotionEvent motionEvent) { - // Note: Using logical or to ensure both functions get called. + // Note: Using logical-or to ensure both functions get called. return mEdgeBackGestureHandler.onTouch(view, motionEvent) | mNavBarGestureHandler.onTouch(view, motionEvent); } + boolean onInterceptTouch(MotionEvent motionEvent) { + // Note: Using logical-or to ensure both functions get called. + return mEdgeBackGestureHandler.onInterceptTouch(motionEvent) + | mNavBarGestureHandler.onInterceptTouch(motionEvent); + } + void onAttachedToWindow() { mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView()); } @@ -168,6 +179,10 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { return mRootView; } + View getLauncherView() { + return mLauncherView; + } + TutorialHandAnimation getHandAnimation() { return mHandCoachingAnimation; } diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 1cd201f99e..2809bd5a96 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -323,11 +323,8 @@ public class CellLayout extends ViewGroup { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (mTouchHelper != null - || (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev))) { - return true; - } - return false; + return mTouchHelper != null + || (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev)); } public void enableHardwareLayer(boolean hasLayer) { diff --git a/src/com/android/launcher3/WorkspaceLayoutManager.java b/src/com/android/launcher3/WorkspaceLayoutManager.java index ea887cc5eb..d6302ce580 100644 --- a/src/com/android/launcher3/WorkspaceLayoutManager.java +++ b/src/com/android/launcher3/WorkspaceLayoutManager.java @@ -130,12 +130,16 @@ public interface WorkspaceLayoutManager { } child.setHapticFeedbackEnabled(false); - child.setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE); + child.setOnLongClickListener(getWorkspaceChildOnLongClickListener()); if (child instanceof DropTarget) { onAddDropTarget((DropTarget) child); } } + default View.OnLongClickListener getWorkspaceChildOnLongClickListener() { + return ItemLongClickListener.INSTANCE_WORKSPACE; + } + Hotseat getHotseat(); CellLayout getScreenWithId(int screenId); diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java index cd84c96171..effb3a4a0c 100644 --- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java @@ -513,8 +513,7 @@ public class LauncherPreviewRenderer extends ContextThemeWrapper } // Setup search view - SearchUiManager searchUiManager = - mRootView.findViewById(R.id.search_container_all_apps); + SearchUiManager searchUiManager = mRootView.findViewById(R.id.search_container_all_apps); mRootView.findViewById(R.id.apps_view).setTranslationY( mDp.heightPx - searchUiManager.getScrollRangeDelta(mInsets)); ViewGroup searchView = (ViewGroup) searchUiManager;