Revert "Moving taskbar lifecycle to TouchInteractionService"
This reverts commit e215fb730bb3d4a357a2c4bf0c082d3c0ad69495.
Reason for revert: DroidMonitor-triggered revert due to breakage https://android-build.googleplex.com/builds/tests/view?invocationId=I13700009003387451&testResultId=TR89423459137251402, bug https://buganizer.corp.google.com/issues/188755902
Bug: 188755902
Change-Id: I4650136975b60f311499ee6ff5b27ab9a32d23d6
diff --git a/quickstep/res/layout/taskbar.xml b/quickstep/res/layout/taskbar.xml
index c436221..240fe55 100644
--- a/quickstep/res/layout/taskbar.xml
+++ b/quickstep/res/layout/taskbar.xml
@@ -22,29 +22,9 @@
<com.android.launcher3.taskbar.TaskbarView
android:id="@+id/taskbar_view"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center"
- android:forceHasOverlappingRendering="false"
- android:layout_gravity="bottom" >
-
- <LinearLayout
- android:id="@+id/system_button_layout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
- android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
- android:forceHasOverlappingRendering="false"
- android:gravity="center" />
-
- <LinearLayout
- android:id="@+id/hotseat_icons_layout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:forceHasOverlappingRendering="false"
- android:gravity="center" />
-
- </com.android.launcher3.taskbar.TaskbarView>
+ android:gravity="center"/>
<com.android.launcher3.taskbar.ImeBarView
android:id="@+id/ime_bar_view"
diff --git a/quickstep/res/layout/taskbar_view.xml b/quickstep/res/layout/taskbar_view.xml
new file mode 100644
index 0000000..34a88ea
--- /dev/null
+++ b/quickstep/res/layout/taskbar_view.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<com.android.launcher3.taskbar.TaskbarView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/taskbar_view"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/taskbar_size"
+ android:background="@android:color/transparent"
+ android:layout_gravity="bottom"
+ android:gravity="center"
+ android:visibility="gone" />
+
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 50453ac..735cb24 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -149,5 +149,4 @@
<!-- Note that this applies to both sides of all icons, so visible space is double this. -->
<dimen name="taskbar_icon_spacing">8dp</dimen>
<dimen name="taskbar_folder_margin">16dp</dimen>
- <dimen name="taskbar_nav_buttons_spacing">16dp</dimen>
</resources>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index bc2c125..e777ee7 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.NO_OFFSET;
+import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
@@ -29,6 +30,7 @@
import android.animation.ValueAnimator;
import android.app.ActivityOptions;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.ServiceConnection;
@@ -49,11 +51,13 @@
import com.android.launcher3.statehandlers.BackButtonAlphaHandler;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager.StateHandler;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarController;
-import com.android.launcher3.taskbar.TaskbarManager;
import com.android.launcher3.taskbar.TaskbarStateHandler;
+import com.android.launcher3.taskbar.TaskbarView;
import com.android.launcher3.uioverrides.RecentsViewStateController;
import com.android.launcher3.util.ActivityOptionsWrapper;
+import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.ObjectWrapper;
import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.RecentsModel;
@@ -63,7 +67,6 @@
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.TouchInteractionService;
-import com.android.quickstep.TouchInteractionService.TISBinder;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
import com.android.quickstep.util.SplitSelectStateController;
@@ -85,6 +88,8 @@
private DepthController mDepthController = new DepthController(this);
private QuickstepTransitionManager mAppTransitionManager;
+ private ServiceConnection mTisBinderConnection;
+ protected TouchInteractionService.TISBinder mTisBinder;
/**
* Reusable command for applying the back button alpha on the background thread.
@@ -95,20 +100,8 @@
private OverviewActionsView mActionsView;
- private @Nullable TaskbarManager mTaskbarManager;
private @Nullable TaskbarController mTaskbarController;
- private final ServiceConnection mTisBinderConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
- mTaskbarManager = ((TISBinder) iBinder).getTaskbarManager();
- mTaskbarManager.setLauncher(BaseQuickstepLauncher.this);
- }
-
- @Override
- public void onServiceDisconnected(ComponentName componentName) { }
- };
private final TaskbarStateHandler mTaskbarStateHandler = new TaskbarStateHandler(this);
-
// Will be updated when dragging from taskbar.
private @Nullable DragOptions mNextWorkspaceDragOptions = null;
private SplitPlaceholderView mSplitPlaceholderView;
@@ -118,6 +111,24 @@
super.onCreate(savedInstanceState);
SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this);
addMultiWindowModeChangedListener(mDepthController);
+ setupTouchInteractionServiceBinder();
+ }
+
+ private void setupTouchInteractionServiceBinder() {
+ Intent intent = new Intent(this, TouchInteractionService.class);
+ mTisBinderConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName componentName, IBinder binder) {
+ mTisBinder = ((TouchInteractionService.TISBinder) binder);
+ mTisBinder.setTaskbarOverviewProxyDelegate(mTaskbarController);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName componentName) {
+ mTisBinder = null;
+ }
+ };
+ bindService(intent, mTisBinderConnection, 0);
}
@Override
@@ -125,12 +136,15 @@
mAppTransitionManager.onActivityDestroyed();
SysUINavigationMode.INSTANCE.get(this).removeModeChangeListener(this);
-
-
- unbindService(mTisBinderConnection);
- if (mTaskbarManager != null) {
- mTaskbarManager.setLauncher(null);
+ if (mTaskbarController != null) {
+ mTaskbarController.cleanup();
+ mTaskbarController = null;
+ if (mTisBinder != null) {
+ mTisBinder.setTaskbarOverviewProxyDelegate(null);
+ unbindService(mTisBinderConnection);
+ }
}
+
super.onDestroy();
}
@@ -257,12 +271,37 @@
mAppTransitionManager = new QuickstepTransitionManager(this);
mAppTransitionManager.registerRemoteAnimations();
- bindService(new Intent(this, TouchInteractionService.class), mTisBinderConnection, 0);
-
+ addTaskbarIfNecessary();
+ addOnDeviceProfileChangeListener(newDp -> addTaskbarIfNecessary());
}
- public void setTaskbarController(TaskbarController taskbarController) {
- mTaskbarController = taskbarController;
+ @Override
+ public void onDisplayInfoChanged(Context context, DisplayController.Info info,
+ int flags) {
+ super.onDisplayInfoChanged(context, info, flags);
+ if ((flags & CHANGE_ACTIVE_SCREEN) != 0) {
+ addTaskbarIfNecessary();
+ }
+ }
+
+ private void addTaskbarIfNecessary() {
+ if (mTaskbarController != null) {
+ mTaskbarController.cleanup();
+ if (mTisBinder != null) {
+ mTisBinder.setTaskbarOverviewProxyDelegate(null);
+ }
+ mTaskbarController = null;
+ }
+ if (mDeviceProfile.isTaskbarPresent) {
+ TaskbarView taskbarViewOnHome = (TaskbarView) mHotseat.getTaskbarView();
+ TaskbarActivityContext taskbarActivityContext = new TaskbarActivityContext(this);
+ mTaskbarController = new TaskbarController(this,
+ taskbarActivityContext.getTaskbarContainerView(), taskbarViewOnHome);
+ mTaskbarController.init();
+ if (mTisBinder != null) {
+ mTisBinder.setTaskbarOverviewProxyDelegate(mTaskbarController);
+ }
+ }
}
public <T extends OverviewActionsView> T getActionsView() {
@@ -301,9 +340,14 @@
}
@Override
+ public boolean isViewInTaskbar(View v) {
+ return mTaskbarController != null && mTaskbarController.isViewInTaskbar(v);
+ }
+
public boolean supportsAdaptiveIconAnimation(View clickedView) {
return mAppTransitionManager.hasControlRemoteAppTransitionPermission()
- && FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM.get();
+ && FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM.get()
+ && !isViewInTaskbar(clickedView);
}
@Override
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 80754a0..1b8fcb3 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1252,6 +1252,7 @@
final boolean launchingFromWidget = mV instanceof LauncherAppWidgetHostView;
final boolean launchingFromRecents = isLaunchingFromRecents(mV, appTargets);
+ final boolean launchingFromTaskbar = mLauncher.isViewInTaskbar(mV);
if (launchingFromWidget) {
composeWidgetLaunchAnimator(anim, (LauncherAppWidgetHostView) mV, appTargets,
wallpaperTargets, nonAppTargets);
@@ -1262,6 +1263,8 @@
launcherClosing);
addCujInstrumentation(
anim, InteractionJankMonitorWrapper.CUJ_APP_LAUNCH_FROM_RECENTS);
+ } else if (launchingFromTaskbar) {
+ // TODO
} else {
composeIconLaunchAnimator(anim, mV, appTargets, wallpaperTargets, nonAppTargets,
launcherClosing);
diff --git a/quickstep/src/com/android/launcher3/taskbar/ButtonProvider.java b/quickstep/src/com/android/launcher3/taskbar/ButtonProvider.java
index 540f748..0d4130d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/ButtonProvider.java
+++ b/quickstep/src/com/android/launcher3/taskbar/ButtonProvider.java
@@ -16,17 +16,12 @@
package com.android.launcher3.taskbar;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_RECENTS;
-
import android.annotation.DrawableRes;
+import android.content.Context;
import android.view.View;
import android.widget.ImageView;
import com.android.launcher3.R;
-import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton;
/**
* Creates Buttons for Taskbar for 3 button nav.
@@ -34,46 +29,47 @@
*/
public class ButtonProvider {
- private final int mMarginLeftRight;
- private final TaskbarActivityContext mContext;
+ private int mMarginLeftRight;
+ private final Context mContext;
- public ButtonProvider(TaskbarActivityContext context) {
+ public ButtonProvider(Context context) {
mContext = context;
- mMarginLeftRight = context.getResources()
- .getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
+ }
+
+ public void setMarginLeftRight(int margin) {
+ mMarginLeftRight = margin;
}
public View getBack() {
// Back button
- return getButtonForDrawable(R.drawable.ic_sysbar_back, BUTTON_BACK);
+ return getButtonForDrawable(R.drawable.ic_sysbar_back);
}
public View getDown() {
// Ime down button
- return getButtonForDrawable(R.drawable.ic_sysbar_back, BUTTON_BACK);
+ return getButtonForDrawable(R.drawable.ic_sysbar_back);
}
public View getHome() {
// Home button
- return getButtonForDrawable(R.drawable.ic_sysbar_home, BUTTON_HOME);
+ return getButtonForDrawable(R.drawable.ic_sysbar_home);
}
public View getRecents() {
// Recents button
- return getButtonForDrawable(R.drawable.ic_sysbar_recent, BUTTON_RECENTS);
+ return getButtonForDrawable(R.drawable.ic_sysbar_recent);
}
public View getImeSwitcher() {
// IME Switcher Button
- return getButtonForDrawable(R.drawable.ic_ime_switcher, BUTTON_IME_SWITCH);
+ return getButtonForDrawable(R.drawable.ic_ime_switcher);
}
- private View getButtonForDrawable(@DrawableRes int drawableId, @TaskbarButton int buttonType) {
+ private View getButtonForDrawable(@DrawableRes int drawableId) {
ImageView buttonView = new ImageView(mContext);
buttonView.setImageResource(drawableId);
buttonView.setBackgroundResource(R.drawable.taskbar_icon_click_feedback_roundrect);
buttonView.setPadding(mMarginLeftRight, 0, mMarginLeftRight, 0);
- buttonView.setOnClickListener(view -> mContext.onNavigationButtonClick(buttonType));
return buttonView;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/ImeBarView.java b/quickstep/src/com/android/launcher3/taskbar/ImeBarView.java
index 287caab..bb3669b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/ImeBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/ImeBarView.java
@@ -16,6 +16,9 @@
package com.android.launcher3.taskbar;
+import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
+import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH;
+
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
@@ -26,6 +29,7 @@
public class ImeBarView extends RelativeLayout {
private ButtonProvider mButtonProvider;
+ private TaskbarController.TaskbarViewCallbacks mControllerCallbacks;
private View mImeView;
public ImeBarView(Context context) {
@@ -40,9 +44,12 @@
super(context, attrs, defStyleAttr);
}
- public void init(ButtonProvider buttonProvider) {
+ public void construct(ButtonProvider buttonProvider) {
mButtonProvider = buttonProvider;
+ }
+ public void init(TaskbarController.TaskbarViewCallbacks taskbarCallbacks) {
+ mControllerCallbacks = taskbarCallbacks;
ActivityContext context = getActivityContext();
RelativeLayout.LayoutParams imeParams = new RelativeLayout.LayoutParams(
context.getDeviceProfile().iconSizePx,
@@ -57,16 +64,24 @@
// Down Arrow
View downView = mButtonProvider.getDown();
+ downView.setOnClickListener(view -> mControllerCallbacks.onNavigationButtonClick(
+ BUTTON_BACK));
downView.setLayoutParams(downParams);
downView.setRotation(-90);
addView(downView);
// IME switcher button
mImeView = mButtonProvider.getImeSwitcher();
+ mImeView.setOnClickListener(view -> mControllerCallbacks.onNavigationButtonClick(
+ BUTTON_IME_SWITCH));
mImeView.setLayoutParams(imeParams);
addView(mImeView);
}
+ public void cleanup() {
+ removeAllViews();
+ }
+
public void setImeSwitcherVisibility(boolean show) {
mImeView.setVisibility(show ? VISIBLE : GONE);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 70f2788..3af51d5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -15,164 +15,56 @@
*/
package com.android.launcher3.taskbar;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-
-import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
-import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;
-
-import android.app.ActivityOptions;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.LauncherApps;
-import android.graphics.PixelFormat;
+import android.content.ContextWrapper;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.os.Process;
-import android.os.SystemProperties;
-import android.util.Log;
-import android.view.ContextThemeWrapper;
-import android.view.Display;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.WindowManager;
-import android.widget.Toast;
-import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
-import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.R;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.dragndrop.DraggableView;
-import com.android.launcher3.folder.Folder;
-import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton;
-import com.android.launcher3.touch.ItemClickHandler;
-import com.android.launcher3.util.PackageManagerHelper;
-import com.android.launcher3.util.Themes;
-import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.views.ActivityContext;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.launcher3.views.BaseDragLayer;
/**
* The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
* that are used by both Launcher and Taskbar (such as Folder) to reference a generic
* ActivityContext and BaseDragLayer instead of the Launcher activity and its DragLayer.
*/
-public class TaskbarActivityContext extends ContextThemeWrapper implements ActivityContext {
-
- private static final boolean ENABLE_THREE_BUTTON_TASKBAR =
- SystemProperties.getBoolean("persist.debug.taskbar_three_button", false);
- private static final String TAG = "TaskbarActivityContext";
-
- private static final String WINDOW_TITLE = "Taskbar";
+public class TaskbarActivityContext extends ContextWrapper implements ActivityContext {
private final DeviceProfile mDeviceProfile;
private final LayoutInflater mLayoutInflater;
private final TaskbarContainerView mTaskbarContainerView;
- private final TaskbarIconController mIconController;
private final MyDragController mDragController;
- private final WindowManager mWindowManager;
- private WindowManager.LayoutParams mWindowLayoutParams;
-
- private final SysUINavigationMode.Mode mNavMode;
- private final TaskbarNavButtonController mNavButtonController;
-
- private final boolean mIsSafeModeEnabled;
-
- @NonNull
- private TaskbarUIController mUIController = TaskbarUIController.DEFAULT;
-
- private final View.OnClickListener mOnTaskbarIconClickListener;
- private final View.OnLongClickListener mOnTaskbarIconLongClickListener;
-
- public TaskbarActivityContext(Context windowContext, DeviceProfile dp,
- TaskbarNavButtonController buttonController) {
- super(windowContext, Themes.getActivityThemeRes(windowContext));
- mDeviceProfile = dp;
- mNavButtonController = buttonController;
- mNavMode = SysUINavigationMode.getMode(windowContext);
- mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
- () -> getPackageManager().isSafeMode());
-
- mOnTaskbarIconLongClickListener =
- new TaskbarDragController(this)::startSystemDragOnLongClick;
- mOnTaskbarIconClickListener = this::onTaskbarIconClicked;
-
+ public TaskbarActivityContext(BaseQuickstepLauncher launcher) {
+ super(launcher);
+ mDeviceProfile = launcher.getDeviceProfile().copy(this);
float taskbarIconSize = getResources().getDimension(R.dimen.taskbar_icon_size);
float iconScale = taskbarIconSize / mDeviceProfile.iconSizePx;
mDeviceProfile.updateIconSize(iconScale, getResources());
mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
+
mTaskbarContainerView = (TaskbarContainerView) mLayoutInflater
.inflate(R.layout.taskbar, null, false);
- mIconController = new TaskbarIconController(this, mTaskbarContainerView);
mDragController = new MyDragController(this);
-
- Display display = windowContext.getDisplay();
- Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
- ? windowContext.getApplicationContext()
- : windowContext.getApplicationContext().createDisplayContext(display);
- mWindowManager = c.getSystemService(WindowManager.class);
}
- public void init() {
- mWindowLayoutParams = new WindowManager.LayoutParams(
- MATCH_PARENT,
- mDeviceProfile.taskbarSize,
- TYPE_APPLICATION_OVERLAY,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- PixelFormat.TRANSLUCENT);
- mWindowLayoutParams.setTitle(WINDOW_TITLE);
- mWindowLayoutParams.packageName = getPackageName();
- mWindowLayoutParams.gravity = Gravity.BOTTOM;
- mWindowLayoutParams.setFitInsetsTypes(0);
- mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
- mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- mWindowLayoutParams.setSystemApplicationOverlay(true);
-
- WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance();
- wmWrapper.setProvidesInsetsTypes(
- mWindowLayoutParams,
- new int[] { ITYPE_EXTRA_NAVIGATION_BAR, ITYPE_BOTTOM_TAPPABLE_ELEMENT }
- );
-
- mIconController.init(mOnTaskbarIconClickListener, mOnTaskbarIconLongClickListener);
- mWindowManager.addView(mTaskbarContainerView, mWindowLayoutParams);
- }
-
- /**
- * Updates the TaskbarContainer height (pass deviceProfile.taskbarSize to reset).
- */
- public void setTaskbarWindowHeight(int height) {
- if (mWindowLayoutParams.height == height) {
- return;
- }
- mWindowLayoutParams.height = height;
- mWindowManager.updateViewLayout(mTaskbarContainerView, mWindowLayoutParams);
- }
-
- public boolean canShowNavButtons() {
- return ENABLE_THREE_BUTTON_TASKBAR && mNavMode == Mode.THREE_BUTTONS;
+ public TaskbarContainerView getTaskbarContainerView() {
+ return mTaskbarContainerView;
}
@Override
@@ -181,7 +73,7 @@
}
@Override
- public TaskbarContainerView getDragLayer() {
+ public BaseDragLayer<TaskbarActivityContext> getDragLayer() {
return mTaskbarContainerView;
}
@@ -200,103 +92,6 @@
return mDragController;
}
- /**
- * Sets a new data-source for this taskbar instance
- */
- public void setUIController(@NonNull TaskbarUIController uiController) {
- mUIController.onDestroy();
- mUIController = uiController;
- mIconController.setUIController(mUIController);
- mUIController.onCreate();
- }
-
- /**
- * Called when this instance of taskbar is no longer needed
- */
- public void onDestroy() {
- setUIController(TaskbarUIController.DEFAULT);
- mIconController.onDestroy();
- mWindowManager.removeViewImmediate(mTaskbarContainerView);
- }
-
- void onNavigationButtonClick(@TaskbarButton int buttonType) {
- mNavButtonController.onButtonClick(buttonType);
- }
-
- public TaskbarIconController getIconController() {
- return mIconController;
- }
-
- /**
- * Updates the TaskbarContainer to MATCH_PARENT vs original Taskbar size.
- */
- protected void setTaskbarWindowFullscreen(boolean fullscreen) {
- setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : getDeviceProfile().taskbarSize);
- }
-
- protected void onTaskbarIconClicked(View view) {
- Object tag = view.getTag();
- if (tag instanceof Task) {
- Task task = (Task) tag;
- ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key,
- ActivityOptions.makeBasic());
- } else if (tag instanceof FolderInfo) {
- FolderIcon folderIcon = (FolderIcon) view;
- Folder folder = folderIcon.getFolder();
- setTaskbarWindowFullscreen(true);
-
- getDragLayer().post(() -> {
- folder.animateOpen();
-
- folder.iterateOverItems((itemInfo, itemView) -> {
- itemView.setOnClickListener(mOnTaskbarIconClickListener);
- itemView.setOnLongClickListener(mOnTaskbarIconLongClickListener);
- // To play haptic when dragging, like other Taskbar items do.
- itemView.setHapticFeedbackEnabled(true);
- return false;
- });
- });
- } else if (tag instanceof WorkspaceItemInfo) {
- WorkspaceItemInfo info = (WorkspaceItemInfo) tag;
- if (info.isDisabled()) {
- ItemClickHandler.handleDisabledItemClicked(info, this);
- } else {
- Intent intent = new Intent(info.getIntent())
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
- Toast.makeText(this, R.string.safemode_shortcut_error,
- Toast.LENGTH_SHORT).show();
- } else if (info.isPromise()) {
- intent = new PackageManagerHelper(this)
- .getMarketIntent(info.getTargetPackage())
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
-
- } else if (info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
- String id = info.getDeepShortcutId();
- String packageName = intent.getPackage();
- getSystemService(LauncherApps.class)
- .startShortcut(packageName, id, null, null, info.user);
- } else if (info.user.equals(Process.myUserHandle())) {
- startActivity(intent);
- } else {
- getSystemService(LauncherApps.class).startMainActivity(
- intent.getComponent(), info.user, intent.getSourceBounds(), null);
- }
- } catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
- Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT)
- .show();
- Log.e(TAG, "Unable to launch. tag=" + info + " intent=" + intent, e);
- }
- }
- } else {
- Log.e(TAG, "Unknown type clicked: " + tag);
- }
-
- AbstractFloatingView.closeAllOpenViews(this);
- }
-
private static class MyDragController extends DragController<TaskbarActivityContext> {
MyDragController(TaskbarActivityContext activity) {
super(activity);
@@ -311,8 +106,7 @@
}
@Override
- protected void exitDrag() {
- }
+ protected void exitDrag() { }
@Override
protected DropTarget getDefaultDropTarget(int[] dropCoordinates) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAnimationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAnimationController.java
index 815efb9..29f6935 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAnimationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAnimationController.java
@@ -21,7 +21,6 @@
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.Utilities;
-import com.android.launcher3.taskbar.TaskbarController.TaskbarAnimationControllerCallbacks;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.SystemUiProxy;
import com.android.systemui.shared.system.QuickStepContract;
@@ -35,7 +34,7 @@
private static final long IME_VISIBILITY_ALPHA_DURATION = 120;
private final BaseQuickstepLauncher mLauncher;
- private final TaskbarAnimationControllerCallbacks mTaskbarCallbacks;
+ private final TaskbarController.TaskbarAnimationControllerCallbacks mTaskbarCallbacks;
// Background alpha.
private final AnimatedFloat mTaskbarBackgroundAlpha = new AnimatedFloat(
@@ -56,7 +55,7 @@
this::updateTranslationY);
public TaskbarAnimationController(BaseQuickstepLauncher launcher,
- TaskbarAnimationControllerCallbacks taskbarCallbacks) {
+ TaskbarController.TaskbarAnimationControllerCallbacks taskbarCallbacks) {
mLauncher = launcher;
mTaskbarCallbacks = taskbarCallbacks;
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarContainerView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarContainerView.java
index 5034791..621bba7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarContainerView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarContainerView.java
@@ -15,6 +15,9 @@
*/
package com.android.launcher3.taskbar;
+import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_FRAME;
+import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
+
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
@@ -29,21 +32,22 @@
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
import com.android.systemui.shared.system.ViewTreeObserverWrapper;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper.OnComputeInsetsListener;
/**
* Top-level ViewGroup that hosts the TaskbarView as well as Views created by it such as Folder.
*/
public class TaskbarContainerView extends BaseDragLayer<TaskbarActivityContext> {
+ private final int[] mTempLoc = new int[2];
private final int mFolderMargin;
private final Paint mTaskbarBackgroundPaint;
- private TaskbarIconController.Callbacks mControllerCallbacks;
- private TaskbarView mTaskbarView;
+ // Initialized in TaskbarController constructor.
+ private TaskbarController.TaskbarContainerViewCallbacks mControllerCallbacks;
- private final OnComputeInsetsListener mTaskbarInsetsComputer = this::onComputeTaskbarInsets;
+ // Initialized in init.
+ private TaskbarView mTaskbarView;
+ private ViewTreeObserverWrapper.OnComputeInsetsListener mTaskbarInsetsComputer;
public TaskbarContainerView(@NonNull Context context) {
this(context, null);
@@ -64,6 +68,15 @@
mFolderMargin = getResources().getDimensionPixelSize(R.dimen.taskbar_folder_margin);
mTaskbarBackgroundPaint = new Paint();
mTaskbarBackgroundPaint.setColor(getResources().getColor(R.color.taskbar_background));
+ }
+
+ protected void construct(TaskbarController.TaskbarContainerViewCallbacks callbacks) {
+ mControllerCallbacks = callbacks;
+ }
+
+ protected void init(TaskbarView taskbarView) {
+ mTaskbarView = taskbarView;
+ mTaskbarInsetsComputer = createTaskbarInsetsComputer();
recreateControllers();
}
@@ -72,24 +85,46 @@
mControllers = new TouchController[0];
}
- public void init(TaskbarIconController.Callbacks callbacks, TaskbarView taskbarView) {
- mControllerCallbacks = callbacks;
- mTaskbarView = taskbarView;
+ private ViewTreeObserverWrapper.OnComputeInsetsListener createTaskbarInsetsComputer() {
+ return insetsInfo -> {
+ if (mControllerCallbacks.isTaskbarTouchable()) {
+ // Accept touches anywhere in our bounds.
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME);
+ } else {
+ // Let touches pass through us.
+ insetsInfo.touchableRegion.setEmpty();
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
+ }
+
+ // TaskbarContainerView provides insets to other apps based on contentInsets. These
+ // insets should stay consistent even if we expand TaskbarContainerView's bounds, e.g.
+ // to show a floating view like Folder. Thus, we set the contentInsets to be where
+ // mTaskbarView is, since its position never changes and insets rather than overlays.
+ int[] loc = mTempLoc;
+ float scale = mTaskbarView.getScaleX();
+ float translationY = mTaskbarView.getTranslationY();
+ mTaskbarView.setScaleX(1);
+ mTaskbarView.setScaleY(1);
+ mTaskbarView.setTranslationY(0);
+ mTaskbarView.getLocationInWindow(loc);
+ mTaskbarView.setScaleX(scale);
+ mTaskbarView.setScaleY(scale);
+ mTaskbarView.setTranslationY(translationY);
+ insetsInfo.contentInsets.left = loc[0];
+ insetsInfo.contentInsets.top = loc[1];
+ insetsInfo.contentInsets.right = getWidth() - (loc[0] + mTaskbarView.getWidth());
+ insetsInfo.contentInsets.bottom = getHeight() - (loc[1] + mTaskbarView.getHeight());
+ };
}
- private void onComputeTaskbarInsets(InsetsInfo insetsInfo) {
- if (mControllerCallbacks != null) {
- mControllerCallbacks.updateInsetsTouchability(insetsInfo);
- }
- }
-
- protected void onDestroy() {
+ protected void cleanup() {
ViewTreeObserverWrapper.removeOnComputeInsetsListener(mTaskbarInsetsComputer);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+
ViewTreeObserverWrapper.addOnComputeInsetsListener(getViewTreeObserver(),
mTaskbarInsetsComputer);
}
@@ -98,7 +133,7 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- onDestroy();
+ cleanup();
}
@Override
@@ -108,25 +143,10 @@
return true;
}
- public void updateImeBarVisibilityAlpha(float alpha) {
- if (mControllerCallbacks != null) {
- mControllerCallbacks.updateImeBarVisibilityAlpha(alpha);
- }
- }
-
@Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
- if (mControllerCallbacks != null) {
- mControllerCallbacks.onContainerViewRemoved();
- }
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- canvas.drawRect(0, canvas.getHeight() - mTaskbarView.getHeight(), canvas.getWidth(),
- canvas.getHeight(), mTaskbarBackgroundPaint);
- super.dispatchDraw(canvas);
+ mControllerCallbacks.onViewRemoved();
}
/**
@@ -138,6 +158,16 @@
return boundingBox;
}
+ protected TaskbarActivityContext getTaskbarActivityContext() {
+ return mActivity;
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ canvas.drawRect(0, canvas.getHeight() - mTaskbarView.getHeight(), canvas.getWidth(),
+ canvas.getHeight(), mTaskbarBackgroundPaint);
+ super.dispatchDraw(canvas);
+ }
/**
* Sets the alpha of the background color behind all the Taskbar contents.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java
index cdae5be..6084e10 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java
@@ -15,83 +15,105 @@
*/
package com.android.launcher3.taskbar;
+import static android.view.View.GONE;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
+import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.app.ActivityOptions;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.RectF;
+import android.inputmethodservice.InputMethodService;
+import android.view.Gravity;
import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
import androidx.annotation.Nullable;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.folder.Folder;
+import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.model.data.FolderInfo;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.states.StateAnimationConfig;
-
+import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton;
+import com.android.launcher3.touch.ItemClickHandler;
+import com.android.launcher3.views.ActivityContext;
+import com.android.quickstep.AnimatedFloat;
+import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.TouchInteractionService.TaskbarOverviewProxyDelegate;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.WindowManagerWrapper;
/**
- * A data source which integrates with a Launcher instance
- * TODO: Rename to have Launcher prefix
+ * Interfaces with Launcher/WindowManager/SystemUI to determine what to show in TaskbarView.
*/
+public class TaskbarController implements TaskbarOverviewProxyDelegate {
-public class TaskbarController extends TaskbarUIController {
+ private static final String WINDOW_TITLE = "Taskbar";
+
+ private final TaskbarContainerView mTaskbarContainerView;
+ private final TaskbarView mTaskbarViewInApp;
+ private final TaskbarView mTaskbarViewOnHome;
+ private final ImeBarView mImeBarView;
private final BaseQuickstepLauncher mLauncher;
+ private final WindowManager mWindowManager;
+ // Layout width and height of the Taskbar in the default state.
+ private final Point mTaskbarSize;
private final TaskbarStateHandler mTaskbarStateHandler;
private final TaskbarAnimationController mTaskbarAnimationController;
private final TaskbarHotseatController mHotseatController;
+ private final TaskbarDragController mDragController;
+ private final TaskbarNavButtonController mNavButtonController;
- private final TaskbarActivityContext mContext;
- final TaskbarContainerView mTaskbarContainerView;
- final TaskbarView mTaskbarView;
+ // Initialized in init().
+ private WindowManager.LayoutParams mWindowLayoutParams;
+ private SysUINavigationMode.Mode mNavMode = SysUINavigationMode.Mode.NO_BUTTON;
+ private final SysUINavigationMode.NavigationModeChangeListener mNavigationModeChangeListener =
+ this::onNavModeChanged;
private @Nullable Animator mAnimator;
private boolean mIsAnimatingToLauncher;
- public TaskbarController(BaseQuickstepLauncher launcher, TaskbarActivityContext context) {
- mContext = context;
- mTaskbarContainerView = context.getDragLayer();
- mTaskbarView = mTaskbarContainerView.findViewById(R.id.taskbar_view);
-
+ public TaskbarController(BaseQuickstepLauncher launcher,
+ TaskbarContainerView taskbarContainerView, TaskbarView taskbarViewOnHome) {
mLauncher = launcher;
+ mTaskbarContainerView = taskbarContainerView;
+ mTaskbarContainerView.construct(createTaskbarContainerViewCallbacks());
+ ButtonProvider buttonProvider = new ButtonProvider(launcher);
+ mTaskbarViewInApp = mTaskbarContainerView.findViewById(R.id.taskbar_view);
+ mTaskbarViewInApp.construct(createTaskbarViewCallbacks(), buttonProvider);
+ mTaskbarViewOnHome = taskbarViewOnHome;
+ mTaskbarViewOnHome.construct(createTaskbarViewCallbacks(), buttonProvider);
+ mImeBarView = mTaskbarContainerView.findViewById(R.id.ime_bar_view);
+ mImeBarView.construct(buttonProvider);
+ mNavButtonController = new TaskbarNavButtonController(launcher);
+ mWindowManager = mLauncher.getWindowManager();
+ mTaskbarSize = new Point(MATCH_PARENT, mLauncher.getDeviceProfile().taskbarSize);
mTaskbarStateHandler = mLauncher.getTaskbarStateHandler();
mTaskbarAnimationController = new TaskbarAnimationController(mLauncher,
createTaskbarAnimationControllerCallbacks());
- mHotseatController = new TaskbarHotseatController(
- mLauncher, mTaskbarView::updateHotseatItems);
- }
-
- @Override
- protected void onCreate() {
- mTaskbarStateHandler.setAnimationController(mTaskbarAnimationController);
- mTaskbarAnimationController.init();
- mHotseatController.init();
- setTaskbarViewVisible(!mLauncher.hasBeenResumed());
- alignRealHotseatWithTaskbar();
- mLauncher.setTaskbarController(this);
- }
-
- @Override
- protected void onDestroy() {
- if (mAnimator != null) {
- // End this first, in case it relies on properties that are about to be cleaned up.
- mAnimator.end();
- }
- mTaskbarStateHandler.setAnimationController(null);
- mTaskbarAnimationController.cleanup();
- mHotseatController.cleanup();
- setTaskbarViewVisible(true);
- mLauncher.getHotseat().setIconsAlpha(1f);
- mLauncher.setTaskbarController(null);
- }
-
- @Override
- protected boolean isTaskbarTouchable() {
- return !mIsAnimatingToLauncher;
+ mHotseatController = new TaskbarHotseatController(mLauncher,
+ createTaskbarHotseatControllerCallbacks());
+ mDragController = new TaskbarDragController(mLauncher);
}
private TaskbarAnimationControllerCallbacks createTaskbarAnimationControllerCallbacks() {
@@ -103,34 +125,245 @@
@Override
public void updateTaskbarVisibilityAlpha(float alpha) {
- mTaskbarView.setAlpha(alpha);
+ mTaskbarViewInApp.setAlpha(alpha);
+ mTaskbarViewOnHome.setAlpha(alpha);
}
@Override
public void updateImeBarVisibilityAlpha(float alpha) {
- mTaskbarContainerView.updateImeBarVisibilityAlpha(alpha);
+ if (mNavMode != SysUINavigationMode.Mode.THREE_BUTTONS) {
+ // TODO Remove sysui IME bar for gesture nav as well
+ return;
+ }
+ mImeBarView.setAlpha(alpha);
+ mImeBarView.setVisibility(alpha == 0 ? GONE : VISIBLE);
}
@Override
public void updateTaskbarScale(float scale) {
- mTaskbarView.setScaleX(scale);
- mTaskbarView.setScaleY(scale);
+ mTaskbarViewInApp.setScaleX(scale);
+ mTaskbarViewInApp.setScaleY(scale);
}
@Override
public void updateTaskbarTranslationY(float translationY) {
if (translationY < 0) {
// Resize to accommodate the max translation we'll reach.
- mContext.setTaskbarWindowHeight(mContext.getDeviceProfile().taskbarSize
+ setTaskbarWindowHeight(mTaskbarSize.y
+ mLauncher.getHotseat().getTaskbarOffsetY());
} else {
- mContext.setTaskbarWindowHeight(mContext.getDeviceProfile().taskbarSize);
+ setTaskbarWindowHeight(mTaskbarSize.y);
}
- mTaskbarView.setTranslationY(translationY);
+ mTaskbarViewInApp.setTranslationY(translationY);
}
};
}
+ private TaskbarContainerViewCallbacks createTaskbarContainerViewCallbacks() {
+ return new TaskbarContainerViewCallbacks() {
+ @Override
+ public void onViewRemoved() {
+ // Ensure no other children present (like Folders, etc)
+ for (int i = 0; i < mTaskbarContainerView.getChildCount(); i++) {
+ View v = mTaskbarContainerView.getChildAt(i);
+ if (!((v instanceof TaskbarView) || (v instanceof ImeBarView))){
+ return;
+ }
+ }
+ setTaskbarWindowFullscreen(false);
+ }
+
+ @Override
+ public boolean isTaskbarTouchable() {
+ return mTaskbarContainerView.getAlpha() > AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD
+ && (mTaskbarViewInApp.getVisibility() == VISIBLE
+ || mImeBarView.getVisibility() == VISIBLE)
+ && !mIsAnimatingToLauncher;
+ }
+ };
+ }
+
+ private TaskbarViewCallbacks createTaskbarViewCallbacks() {
+ return new TaskbarViewCallbacks() {
+ @Override
+ public View.OnClickListener getItemOnClickListener() {
+ return view -> {
+ Object tag = view.getTag();
+ if (tag instanceof Task) {
+ Task task = (Task) tag;
+ ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key,
+ ActivityOptions.makeBasic());
+ } else if (tag instanceof FolderInfo) {
+ FolderIcon folderIcon = (FolderIcon) view;
+ Folder folder = folderIcon.getFolder();
+
+ setTaskbarWindowFullscreen(true);
+
+ mTaskbarContainerView.post(() -> {
+ folder.animateOpen();
+
+ folder.iterateOverItems((itemInfo, itemView) -> {
+ itemView.setOnClickListener(getItemOnClickListener());
+ itemView.setOnLongClickListener(getItemOnLongClickListener());
+ // To play haptic when dragging, like other Taskbar items do.
+ itemView.setHapticFeedbackEnabled(true);
+ return false;
+ });
+ });
+ } else {
+ ItemClickHandler.INSTANCE.onClick(view);
+ }
+
+ AbstractFloatingView.closeAllOpenViews(
+ mTaskbarContainerView.getTaskbarActivityContext());
+ };
+ }
+
+ @Override
+ public View.OnLongClickListener getItemOnLongClickListener() {
+ return mDragController::startSystemDragOnLongClick;
+ }
+
+ @Override
+ public int getEmptyHotseatViewVisibility(TaskbarView taskbarView) {
+ // When on the home screen, we want the empty hotseat views to take up their full
+ // space so that the others line up with the home screen hotseat.
+ boolean isOnHomeScreen = taskbarView == mTaskbarViewOnHome
+ || mLauncher.hasBeenResumed() || mIsAnimatingToLauncher;
+ return isOnHomeScreen ? INVISIBLE : GONE;
+ }
+
+ @Override
+ public float getNonIconScale(TaskbarView taskbarView) {
+ return taskbarView == mTaskbarViewOnHome ? getTaskbarScaleOnHome() : 1f;
+ }
+
+ @Override
+ public void onItemPositionsChanged(TaskbarView taskbarView) {
+ if (taskbarView == mTaskbarViewOnHome) {
+ alignRealHotseatWithTaskbar();
+ }
+ }
+
+ @Override
+ public void onNavigationButtonClick(@TaskbarButton int buttonType) {
+ mNavButtonController.onButtonClick(buttonType);
+ }
+ };
+ }
+
+ private TaskbarHotseatControllerCallbacks createTaskbarHotseatControllerCallbacks() {
+ return new TaskbarHotseatControllerCallbacks() {
+ @Override
+ public void updateHotseatItems(ItemInfo[] hotseatItemInfos) {
+ mTaskbarViewInApp.updateHotseatItems(hotseatItemInfos);
+ }
+ };
+ }
+
+ /**
+ * Initializes the Taskbar, including adding it to the screen.
+ */
+ public void init() {
+ mNavMode = SysUINavigationMode.INSTANCE.get(mLauncher)
+ .addModeChangeListener(mNavigationModeChangeListener);
+ mTaskbarViewInApp.init(mHotseatController.getNumHotseatIcons(), mNavMode);
+ mTaskbarViewOnHome.init(mHotseatController.getNumHotseatIcons(), mNavMode);
+ mTaskbarContainerView.init(mTaskbarViewInApp);
+ mImeBarView.init(createTaskbarViewCallbacks());
+ addToWindowManager();
+ mTaskbarStateHandler.setTaskbarCallbacks(createTaskbarStateHandlerCallbacks());
+ mTaskbarAnimationController.init();
+ mHotseatController.init();
+
+ setWhichTaskbarViewIsVisible(mLauncher.hasBeenResumed()
+ ? mTaskbarViewOnHome
+ : mTaskbarViewInApp);
+ }
+
+ private TaskbarStateHandlerCallbacks createTaskbarStateHandlerCallbacks() {
+ return new TaskbarStateHandlerCallbacks() {
+ @Override
+ public AnimatedFloat getAlphaTarget() {
+ return mTaskbarAnimationController.getTaskbarVisibilityForLauncherState();
+ }
+
+ @Override
+ public AnimatedFloat getScaleTarget() {
+ return mTaskbarAnimationController.getTaskbarScaleForLauncherState();
+ }
+
+ @Override
+ public AnimatedFloat getTranslationYTarget() {
+ return mTaskbarAnimationController.getTaskbarTranslationYForLauncherState();
+ }
+ };
+ }
+
+ /**
+ * Removes the Taskbar from the screen, and removes any obsolete listeners etc.
+ */
+ public void cleanup() {
+ if (mAnimator != null) {
+ // End this first, in case it relies on properties that are about to be cleaned up.
+ mAnimator.end();
+ }
+
+ mTaskbarViewInApp.cleanup();
+ mTaskbarViewOnHome.cleanup();
+ mTaskbarContainerView.cleanup();
+ mImeBarView.cleanup();
+ removeFromWindowManager();
+ mTaskbarStateHandler.setTaskbarCallbacks(null);
+ mTaskbarAnimationController.cleanup();
+ mHotseatController.cleanup();
+
+ setWhichTaskbarViewIsVisible(null);
+ SysUINavigationMode.INSTANCE.get(mLauncher)
+ .removeModeChangeListener(mNavigationModeChangeListener);
+ }
+
+ private void removeFromWindowManager() {
+ mWindowManager.removeViewImmediate(mTaskbarContainerView);
+ }
+
+ private void addToWindowManager() {
+ final int gravity = Gravity.BOTTOM;
+
+ mWindowLayoutParams = new WindowManager.LayoutParams(
+ mTaskbarSize.x,
+ mTaskbarSize.y,
+ TYPE_APPLICATION_OVERLAY,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ PixelFormat.TRANSLUCENT);
+ mWindowLayoutParams.setTitle(WINDOW_TITLE);
+ mWindowLayoutParams.packageName = mLauncher.getPackageName();
+ mWindowLayoutParams.gravity = gravity;
+ mWindowLayoutParams.setFitInsetsTypes(0);
+ mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+ mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ mWindowLayoutParams.setSystemApplicationOverlay(true);
+
+ WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance();
+ wmWrapper.setProvidesInsetsTypes(
+ mWindowLayoutParams,
+ new int[] { ITYPE_EXTRA_NAVIGATION_BAR, ITYPE_BOTTOM_TAPPABLE_ELEMENT }
+ );
+
+ TaskbarContainerView.LayoutParams taskbarLayoutParams =
+ new TaskbarContainerView.LayoutParams(mTaskbarSize.x, mTaskbarSize.y);
+ taskbarLayoutParams.gravity = gravity;
+ mTaskbarViewInApp.setLayoutParams(taskbarLayoutParams);
+
+ mWindowManager.addView(mTaskbarContainerView, mWindowLayoutParams);
+ }
+
+ private void onNavModeChanged(SysUINavigationMode.Mode newMode) {
+ mNavMode = newMode;
+ cleanup();
+ init();
+ }
+
/**
* Should be called from onResume() and onPause(), and animates the Taskbar accordingly.
*/
@@ -168,14 +401,13 @@
@Override
public void onAnimationStart(Animator animation) {
mIsAnimatingToLauncher = true;
- mTaskbarView.setHolesAllowedInLayout(true);
- mTaskbarView.updateHotseatItemsVisibility();
+ mTaskbarViewInApp.updateHotseatItemsVisibility();
}
@Override
public void onAnimationEnd(Animator animation) {
mIsAnimatingToLauncher = false;
- setTaskbarViewVisible(false);
+ setWhichTaskbarViewIsVisible(mTaskbarViewOnHome);
}
});
@@ -188,21 +420,44 @@
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- mTaskbarView.updateHotseatItemsVisibility();
- setTaskbarViewVisible(true);
+ mTaskbarViewInApp.updateHotseatItemsVisibility();
+ setWhichTaskbarViewIsVisible(mTaskbarViewInApp);
}
@Override
public void onAnimationEnd(Animator animation) {
- mTaskbarView.setHolesAllowedInLayout(false);
}
});
return anim.buildAnim();
}
- @Override
- protected void onImeVisible(TaskbarContainerView containerView, boolean isVisible) {
- mTaskbarAnimationController.animateToVisibilityForIme(isVisible ? 0 : 1);
+ /**
+ * Should be called when the IME visibility changes, so we can hide/show Taskbar accordingly.
+ */
+ public void setIsImeVisible(boolean isImeVisible) {
+ mTaskbarAnimationController.animateToVisibilityForIme(isImeVisible ? 0 : 1);
+ blockTaskbarTouchesForIme(isImeVisible);
+ }
+
+ /**
+ * When in 3 button nav, the above doesn't get called since we prevent sysui nav bar from
+ * instantiating at all, which is what's responsible for sending sysui state flags over.
+ *
+ * @param vis IME visibility flag
+ * @param backDisposition Used to determine back button behavior for software keyboard
+ * See BACK_DISPOSITION_* constants in {@link InputMethodService}
+ */
+ public void updateImeStatus(int displayId, int vis, int backDisposition,
+ boolean showImeSwitcher) {
+ if (displayId != mTaskbarContainerView.getContext().getDisplayId() ||
+ mNavMode != SysUINavigationMode.Mode.THREE_BUTTONS) {
+ return;
+ }
+
+ boolean imeVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
+ mTaskbarAnimationController.animateToVisibilityForIme(imeVisible ? 0 : 1);
+ mImeBarView.setImeSwitcherVisibility(showImeSwitcher);
+ blockTaskbarTouchesForIme(imeVisible);
}
/**
@@ -217,17 +472,24 @@
* @return Whether any Taskbar item could handle the given MotionEvent if given the chance.
*/
public boolean isEventOverAnyTaskbarItem(MotionEvent ev) {
- return mTaskbarView.isEventOverAnyItem(ev);
+ return mTaskbarViewInApp.isEventOverAnyItem(ev);
}
public boolean isDraggingItem() {
- return mTaskbarView.isDraggingItem();
+ return mTaskbarViewInApp.isDraggingItem() || mTaskbarViewOnHome.isDraggingItem();
+ }
+
+ /**
+ * @return Whether the given View is in the same window as Taskbar.
+ */
+ public boolean isViewInTaskbar(View v) {
+ return mTaskbarContainerView.isAttachedToWindow()
+ && mTaskbarContainerView.getWindowId().equals(v.getWindowId());
}
/**
* Pads the Hotseat to line up exactly with Taskbar's copy of the Hotseat.
*/
- @Override
public void alignRealHotseatWithTaskbar() {
Rect hotseatBounds = new Rect();
DeviceProfile grid = mLauncher.getDeviceProfile();
@@ -236,28 +498,60 @@
int hotseatTopDiff = hotseatHeight - grid.taskbarSize - taskbarOffset;
int hotseatBottomDiff = taskbarOffset;
- RectF hotseatBoundsF = mTaskbarView.getHotseatBounds();
- Utilities.scaleRectFAboutPivot(hotseatBoundsF, getTaskbarScaleOnHome(),
- mTaskbarView.getPivotX(), mTaskbarView.getPivotY());
- hotseatBoundsF.round(hotseatBounds);
+ mTaskbarViewOnHome.getHotseatBounds().roundOut(hotseatBounds);
mLauncher.getHotseat().setPadding(hotseatBounds.left,
hotseatBounds.top + hotseatTopDiff,
- mTaskbarView.getWidth() - hotseatBounds.right,
- mTaskbarView.getHeight() - hotseatBounds.bottom + hotseatBottomDiff);
+ mTaskbarViewOnHome.getWidth() - hotseatBounds.right,
+ mTaskbarViewOnHome.getHeight() - hotseatBounds.bottom + hotseatBottomDiff);
+ }
+
+ private void setWhichTaskbarViewIsVisible(@Nullable TaskbarView visibleTaskbar) {
+ mTaskbarViewInApp.setVisibility(visibleTaskbar == mTaskbarViewInApp
+ ? VISIBLE : INVISIBLE);
+ mTaskbarViewOnHome.setVisibility(visibleTaskbar == mTaskbarViewOnHome
+ ? VISIBLE : INVISIBLE);
+ mLauncher.getHotseat().setIconsAlpha(visibleTaskbar != mTaskbarViewInApp ? 1f : 0f);
+ }
+
+ private void blockTaskbarTouchesForIme(boolean block) {
+ mTaskbarViewOnHome.setTouchesEnabled(!block);
+ mTaskbarViewInApp.setTouchesEnabled(!block);
}
/**
* Returns the ratio of the taskbar icon size on home vs in an app.
*/
public float getTaskbarScaleOnHome() {
- DeviceProfile inAppDp = mContext.getDeviceProfile();
- DeviceProfile onHomeDp = mLauncher.getDeviceProfile();
+ DeviceProfile inAppDp = mTaskbarContainerView.getTaskbarActivityContext()
+ .getDeviceProfile();
+ DeviceProfile onHomeDp = ActivityContext.lookupContext(mTaskbarViewOnHome.getContext())
+ .getDeviceProfile();
return (float) onHomeDp.cellWidthPx / inAppDp.cellWidthPx;
}
- void setTaskbarViewVisible(boolean isVisible) {
- mTaskbarView.setIconsVisibility(isVisible);
- mLauncher.getHotseat().setIconsAlpha(isVisible ? 0f : 1f);
+ /**
+ * Updates the TaskbarContainer to MATCH_PARENT vs original Taskbar size.
+ */
+ private void setTaskbarWindowFullscreen(boolean fullscreen) {
+ setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : mTaskbarSize.y);
+ }
+
+ /**
+ * Updates the TaskbarContainer height (pass mTaskbarSize.y to reset).
+ */
+ private void setTaskbarWindowHeight(int height) {
+ mWindowLayoutParams.width = mTaskbarSize.x;
+ mWindowLayoutParams.height = height;
+ mWindowManager.updateViewLayout(mTaskbarContainerView, mWindowLayoutParams);
+ }
+
+ /**
+ * Contains methods that TaskbarStateHandler can call to interface with TaskbarController.
+ */
+ protected interface TaskbarStateHandlerCallbacks {
+ AnimatedFloat getAlphaTarget();
+ AnimatedFloat getScaleTarget();
+ AnimatedFloat getTranslationYTarget();
}
/**
@@ -271,4 +565,32 @@
void updateTaskbarScale(float scale);
void updateTaskbarTranslationY(float translationY);
}
+
+ /**
+ * Contains methods that TaskbarContainerView can call to interface with TaskbarController.
+ */
+ protected interface TaskbarContainerViewCallbacks {
+ void onViewRemoved();
+ boolean isTaskbarTouchable();
+ }
+
+ /**
+ * Contains methods that TaskbarView can call to interface with TaskbarController.
+ */
+ protected interface TaskbarViewCallbacks {
+ View.OnClickListener getItemOnClickListener();
+ View.OnLongClickListener getItemOnLongClickListener();
+ int getEmptyHotseatViewVisibility(TaskbarView taskbarView);
+ /** Returns how much to scale non-icon elements such as spacing and dividers. */
+ float getNonIconScale(TaskbarView taskbarView);
+ void onItemPositionsChanged(TaskbarView taskbarView);
+ void onNavigationButtonClick(@TaskbarButton int buttonType);
+ }
+
+ /**
+ * Contains methods that TaskbarHotseatController can call to interface with TaskbarController.
+ */
+ protected interface TaskbarHotseatControllerCallbacks {
+ void updateHotseatItems(ItemInfo[] hotseatItemInfos);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index ee44927..5eb34cb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -20,7 +20,6 @@
import android.content.ClipData;
import android.content.ClipDescription;
-import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.res.Resources;
@@ -30,6 +29,7 @@
import android.view.DragEvent;
import android.view.View;
+import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
@@ -43,12 +43,12 @@
*/
public class TaskbarDragController {
- private final Context mContext;
+ private final BaseQuickstepLauncher mLauncher;
private final int mDragIconSize;
- public TaskbarDragController(Context context) {
- mContext = context;
- Resources resources = mContext.getResources();
+ public TaskbarDragController(BaseQuickstepLauncher launcher) {
+ mLauncher = launcher;
+ Resources resources = mLauncher.getResources();
mDragIconSize = resources.getDimensionPixelSize(R.dimen.taskbar_icon_drag_icon_size);
}
@@ -63,6 +63,7 @@
}
BubbleTextView btv = (BubbleTextView) view;
+
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view) {
@Override
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
@@ -86,7 +87,7 @@
Intent intent = null;
if (tag instanceof WorkspaceItemInfo) {
WorkspaceItemInfo item = (WorkspaceItemInfo) tag;
- LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
+ LauncherApps launcherApps = mLauncher.getSystemService(LauncherApps.class);
clipDescription = new ClipDescription(item.title,
new String[] {
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarHotseatController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarHotseatController.java
index 91cf7ef..68829cd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarHotseatController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarHotseatController.java
@@ -26,8 +26,6 @@
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.model.data.ItemInfo;
-import java.util.function.Consumer;
-
/**
* Works with TaskbarController to update the TaskbarView's Hotseat items.
*/
@@ -35,12 +33,13 @@
private final BaseQuickstepLauncher mLauncher;
private final Hotseat mHotseat;
- private final Consumer<ItemInfo[]> mTaskbarCallbacks;
+ private final TaskbarController.TaskbarHotseatControllerCallbacks mTaskbarCallbacks;
private final int mNumHotseatIcons;
private final DragController.DragListener mDragListener = new DragController.DragListener() {
@Override
- public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) { }
+ public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+ }
@Override
public void onDragEnd() {
@@ -48,8 +47,8 @@
}
};
- public TaskbarHotseatController(
- BaseQuickstepLauncher launcher, Consumer<ItemInfo[]> taskbarCallbacks) {
+ public TaskbarHotseatController(BaseQuickstepLauncher launcher,
+ TaskbarController.TaskbarHotseatControllerCallbacks taskbarCallbacks) {
mLauncher = launcher;
mHotseat = mLauncher.getHotseat();
mTaskbarCallbacks = taskbarCallbacks;
@@ -86,6 +85,10 @@
}
}
- mTaskbarCallbacks.accept(hotseatItemInfos);
+ mTaskbarCallbacks.updateHotseatItems(hotseatItemInfos);
+ }
+
+ protected int getNumHotseatIcons() {
+ return mNumHotseatIcons;
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java
deleted file mode 100644
index 2a37915..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2021 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.launcher3.taskbar;
-
-import static android.view.View.GONE;
-import static android.view.View.VISIBLE;
-
-import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_FRAME;
-import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
-
-import android.graphics.Rect;
-import android.inputmethodservice.InputMethodService;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
-
-import androidx.annotation.NonNull;
-
-import com.android.launcher3.R;
-import com.android.launcher3.anim.AlphaUpdateListener;
-import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
-
-/**
- * Controller for taskbar icon UI
- */
-public class TaskbarIconController {
-
- private final Rect mTempRect = new Rect();
-
- private final TaskbarActivityContext mActivity;
- private final TaskbarContainerView mContainerView;
-
- private final TaskbarView mTaskbarView;
- private final ImeBarView mImeBarView;
-
- @NonNull
- private TaskbarUIController mUIController = TaskbarUIController.DEFAULT;
-
- TaskbarIconController(TaskbarActivityContext activity, TaskbarContainerView containerView) {
- mActivity = activity;
- mContainerView = containerView;
- mTaskbarView = mContainerView.findViewById(R.id.taskbar_view);
- mImeBarView = mContainerView.findViewById(R.id.ime_bar_view);
- }
-
- public void init(OnClickListener clickListener, OnLongClickListener longClickListener) {
- mContainerView.addOnLayoutChangeListener((v, a, b, c, d, e, f, g, h) ->
- mUIController.alignRealHotseatWithTaskbar());
-
- ButtonProvider buttonProvider = new ButtonProvider(mActivity);
- mImeBarView.init(buttonProvider);
- mTaskbarView.construct(clickListener, longClickListener, buttonProvider);
- mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
-
- mContainerView.init(new Callbacks(), mTaskbarView);
- }
-
- public void onDestroy() {
- mContainerView.onDestroy();
- }
-
- public void setUIController(@NonNull TaskbarUIController uiController) {
- mUIController = uiController;
- }
-
- /**
- * When in 3 button nav, the above doesn't get called since we prevent sysui nav bar from
- * instantiating at all, which is what's responsible for sending sysui state flags over.
- *
- * @param vis IME visibility flag
- */
- public void updateImeStatus(int displayId, int vis, boolean showImeSwitcher) {
- if (displayId != mActivity.getDisplayId() || !mActivity.canShowNavButtons()) {
- return;
- }
-
- mImeBarView.setImeSwitcherVisibility(showImeSwitcher);
- setImeIsVisible((vis & InputMethodService.IME_VISIBLE) != 0);
- }
-
- /**
- * Should be called when the IME visibility changes, so we can hide/show Taskbar accordingly.
- */
- public void setImeIsVisible(boolean isImeVisible) {
- mTaskbarView.setTouchesEnabled(!isImeVisible);
- mUIController.onImeVisible(mContainerView, isImeVisible);
- }
-
- /**
- * Callbacks for {@link TaskbarContainerView} to interact with the icon controller
- */
- public class Callbacks {
-
- /**
- * Called to update the touchable insets
- */
- public void updateInsetsTouchability(InsetsInfo insetsInfo) {
- insetsInfo.touchableRegion.setEmpty();
- if (mContainerView.getAlpha() < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
- // Let touches pass through us.
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
- } else if (mImeBarView.getVisibility() == VISIBLE) {
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME);
- } else if (!mUIController.isTaskbarTouchable()) {
- // Let touches pass through us.
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
- } else if (mTaskbarView.areIconsVisible()) {
- // Buttons are visible, take over the full taskbar area
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME);
- } else {
- if (mTaskbarView.mSystemButtonContainer.getVisibility() == VISIBLE) {
- mContainerView.getDescendantRectRelativeToSelf(
- mTaskbarView.mSystemButtonContainer, mTempRect);
- insetsInfo.touchableRegion.set(mTempRect);
- }
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
- }
-
- // TaskbarContainerView provides insets to other apps based on contentInsets. These
- // insets should stay consistent even if we expand TaskbarContainerView's bounds, e.g.
- // to show a floating view like Folder. Thus, we set the contentInsets to be where
- // mTaskbarView is, since its position never changes and insets rather than overlays.
- insetsInfo.contentInsets.left = mTaskbarView.getLeft();
- insetsInfo.contentInsets.top = mTaskbarView.getTop();
- insetsInfo.contentInsets.right = mContainerView.getWidth() - mTaskbarView.getRight();
- insetsInfo.contentInsets.bottom = mContainerView.getHeight() - mTaskbarView.getBottom();
- }
-
- public void onContainerViewRemoved() {
- int count = mContainerView.getChildCount();
- // Ensure no other children present (like Folders, etc)
- for (int i = 0; i < count; i++) {
- View v = mContainerView.getChildAt(i);
- if (!((v instanceof TaskbarView) || (v instanceof ImeBarView))) {
- return;
- }
- }
- mActivity.setTaskbarWindowFullscreen(false);
- }
-
- public void updateImeBarVisibilityAlpha(float alpha) {
- if (!mActivity.canShowNavButtons()) {
- // TODO Remove sysui IME bar for gesture nav as well
- return;
- }
- mImeBarView.setAlpha(alpha);
- mImeBarView.setVisibility(alpha == 0 ? GONE : VISIBLE);
- }
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
deleted file mode 100644
index b9eec93..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2021 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.launcher3.taskbar;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-
-import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
-import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
-import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
-
-import android.content.Context;
-import android.hardware.display.DisplayManager;
-import android.inputmethodservice.InputMethodService;
-import android.view.Display;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BaseQuickstepLauncher;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.DisplayController.Info;
-import com.android.quickstep.SysUINavigationMode;
-import com.android.quickstep.SysUINavigationMode.Mode;
-import com.android.quickstep.TouchInteractionService;
-
-/**
- * Class to manager taskbar lifecycle
- */
-public class TaskbarManager implements DisplayController.DisplayInfoChangeListener,
- SysUINavigationMode.NavigationModeChangeListener {
-
- private final Context mContext;
- private final DisplayController mDisplayController;
- private final SysUINavigationMode mSysUINavigationMode;
- private final TaskbarNavButtonController mNavButtonController;
-
- private TaskbarActivityContext mTaskbarActivityContext;
- private BaseQuickstepLauncher mLauncher;
-
- private static final int CHANGE_FLAGS =
- CHANGE_ACTIVE_SCREEN | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS;
-
- public TaskbarManager(TouchInteractionService service) {
- mDisplayController = DisplayController.INSTANCE.get(service);
- mSysUINavigationMode = SysUINavigationMode.INSTANCE.get(service);
- Display display =
- service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
- mContext = service.createWindowContext(display, TYPE_APPLICATION_OVERLAY, null);
- mNavButtonController = new TaskbarNavButtonController(service);
-
- mDisplayController.addChangeListener(this);
- mSysUINavigationMode.addModeChangeListener(this);
- recreateTaskbar();
- }
-
- @Override
- public void onNavigationModeChanged(Mode newMode) {
- recreateTaskbar();
- }
-
- @Override
- public void onDisplayInfoChanged(Context context, Info info, int flags) {
- if ((flags & CHANGE_FLAGS) != 0) {
- recreateTaskbar();
- }
- }
-
- private void destroyExistingTaskbar() {
- if (mTaskbarActivityContext != null) {
- mTaskbarActivityContext.onDestroy();
- mTaskbarActivityContext = null;
- }
- }
-
- /**
- * Sets or clears a launcher to act as taskbar callback
- */
- public void setLauncher(@Nullable BaseQuickstepLauncher launcher) {
- mLauncher = launcher;
- if (mTaskbarActivityContext != null) {
- mTaskbarActivityContext.setUIController(mLauncher == null
- ? TaskbarUIController.DEFAULT
- : new TaskbarController(launcher, mTaskbarActivityContext));
- }
- }
-
- private void recreateTaskbar() {
- destroyExistingTaskbar();
- if (!FeatureFlags.ENABLE_TASKBAR.get()) {
- return;
- }
- DeviceProfile dp = LauncherAppState.getIDP(mContext).getDeviceProfile(mContext);
- if (!dp.isTaskbarPresent) {
- return;
- }
- mTaskbarActivityContext = new TaskbarActivityContext(
- mContext, dp.copy(mContext), mNavButtonController);
- mTaskbarActivityContext.init();
- if (mLauncher != null) {
- mTaskbarActivityContext.setUIController(
- new TaskbarController(mLauncher, mTaskbarActivityContext));
- }
- }
-
- /**
- * See {@link com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags}
- * @param systemUiStateFlags The latest SystemUiStateFlags
- */
- public void onSystemUiFlagsChanged(int systemUiStateFlags) {
- boolean isImeVisible = (systemUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0;
- if (mTaskbarActivityContext != null) {
- mTaskbarActivityContext.getIconController().setImeIsVisible(isImeVisible);
- }
- }
-
- /**
- * When in 3 button nav, the above doesn't get called since we prevent sysui nav bar from
- * instantiating at all, which is what's responsible for sending sysui state flags over.
- *
- * @param vis IME visibility flag
- * @param backDisposition Used to determine back button behavior for software keyboard
- * See BACK_DISPOSITION_* constants in {@link InputMethodService}
- */
- public void updateImeStatus(int displayId, int vis, int backDisposition,
- boolean showImeSwitcher) {
- if (mTaskbarActivityContext != null) {
- mTaskbarActivityContext.getIconController()
- .updateImeStatus(displayId, vis, showImeSwitcher);
- }
- }
-
- /**
- * Called when the manager is no longer needed
- */
- public void destroy() {
- destroyExistingTaskbar();
- mDisplayController.removeChangeListener(this);
- mSysUINavigationMode.removeModeChangeListener(this);
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 3b5afad..54e1610 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -16,8 +16,7 @@
package com.android.launcher3.taskbar;
-import static android.view.Display.DEFAULT_DISPLAY;
-
+import android.content.Context;
import android.content.Intent;
import android.view.inputmethod.InputMethodManager;
@@ -54,10 +53,11 @@
static final int BUTTON_RECENTS = BUTTON_HOME << 1;
static final int BUTTON_IME_SWITCH = BUTTON_RECENTS << 1;
- private final TouchInteractionService mService;
- public TaskbarNavButtonController(TouchInteractionService service) {
- mService = service;
+ private final Context mContext;
+
+ public TaskbarNavButtonController(Context context) {
+ mContext = context;
}
public void onButtonClick(@TaskbarButton int buttonType) {
@@ -78,13 +78,13 @@
}
private void navigateHome() {
- mService.startActivity(new Intent(Intent.ACTION_MAIN)
+ mContext.startActivity(new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
private void navigateToOverview() {
- mService.getOverviewCommandHelper()
+ TouchInteractionService.getInstance().getOverviewCommandHelper()
.addCommand(OverviewCommandHelper.TYPE_SHOW);
}
@@ -93,8 +93,8 @@
}
private void showIMESwitcher() {
- mService.getSystemService(InputMethodManager.class)
- .showInputMethodPickerFromSystem(true /* showAuxiliarySubtypes */,
- DEFAULT_DISPLAY);
+ mContext.getSystemService(InputMethodManager.class).showInputMethodPickerFromSystem(
+ true /* showAuxiliarySubtypes */, mContext.getDisplayId());
}
+
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java
index a701aae..6ea51fa 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java
@@ -24,52 +24,59 @@
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.quickstep.AnimatedFloat;
/**
* StateHandler to animate Taskbar according to Launcher's state machine. Does nothing if Taskbar
- * isn't present (i.e. {@link #setAnimationController} is never called).
+ * isn't present (i.e. {@link #setTaskbarCallbacks} is never called).
*/
public class TaskbarStateHandler implements StateManager.StateHandler<LauncherState> {
private final BaseQuickstepLauncher mLauncher;
// Contains Taskbar-related methods and fields we should aniamte. If null, don't do anything.
- private @Nullable TaskbarAnimationController mAnimationController = null;
+ private @Nullable TaskbarController.TaskbarStateHandlerCallbacks mTaskbarCallbacks = null;
public TaskbarStateHandler(BaseQuickstepLauncher launcher) {
mLauncher = launcher;
}
- public void setAnimationController(TaskbarAnimationController callbacks) {
- mAnimationController = callbacks;
+ public void setTaskbarCallbacks(TaskbarController.TaskbarStateHandlerCallbacks callbacks) {
+ mTaskbarCallbacks = callbacks;
}
@Override
public void setState(LauncherState state) {
- setState(state, PropertySetter.NO_ANIM_PROPERTY_SETTER);
+ if (mTaskbarCallbacks == null) {
+ return;
+ }
+
+ AnimatedFloat alphaTarget = mTaskbarCallbacks.getAlphaTarget();
+ AnimatedFloat scaleTarget = mTaskbarCallbacks.getScaleTarget();
+ AnimatedFloat translationYTarget = mTaskbarCallbacks.getTranslationYTarget();
+ boolean isTaskbarVisible = (state.getVisibleElements(mLauncher) & TASKBAR) != 0;
+ alphaTarget.updateValue(isTaskbarVisible ? 1f : 0f);
+ scaleTarget.updateValue(state.getTaskbarScale(mLauncher));
+ translationYTarget.updateValue(state.getTaskbarTranslationY(mLauncher));
}
@Override
public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
PendingAnimation animation) {
- setState(toState, animation);
- }
-
- private void setState(LauncherState toState, PropertySetter setter) {
- if (mAnimationController == null) {
+ if (mTaskbarCallbacks == null) {
return;
}
+ AnimatedFloat alphaTarget = mTaskbarCallbacks.getAlphaTarget();
+ AnimatedFloat scaleTarget = mTaskbarCallbacks.getScaleTarget();
+ AnimatedFloat translationYTarget = mTaskbarCallbacks.getTranslationYTarget();
boolean isTaskbarVisible = (toState.getVisibleElements(mLauncher) & TASKBAR) != 0;
- setter.setFloat(mAnimationController.getTaskbarVisibilityForLauncherState(),
- AnimatedFloat.VALUE, isTaskbarVisible ? 1f : 0f, LINEAR);
- setter.setFloat(mAnimationController.getTaskbarScaleForLauncherState(),
- AnimatedFloat.VALUE, toState.getTaskbarScale(mLauncher), LINEAR);
- setter.setFloat(mAnimationController.getTaskbarTranslationYForLauncherState(),
- AnimatedFloat.VALUE, toState.getTaskbarTranslationY(mLauncher), ACCEL_DEACCEL);
+ animation.setFloat(alphaTarget, AnimatedFloat.VALUE, isTaskbarVisible ? 1f : 0f, LINEAR);
+ animation.setFloat(scaleTarget, AnimatedFloat.VALUE, toState.getTaskbarScale(mLauncher),
+ LINEAR);
+ animation.setFloat(translationYTarget, AnimatedFloat.VALUE,
+ toState.getTaskbarTranslationY(mLauncher), ACCEL_DEACCEL);
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
deleted file mode 100644
index e16f5e6..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2021 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.launcher3.taskbar;
-
-/**
- * Base class for providing different taskbar UI
- */
-public class TaskbarUIController {
-
- public static final TaskbarUIController DEFAULT = new TaskbarUIController();
-
- /**
- * Pads the Hotseat to line up exactly with Taskbar's copy of the Hotseat.
- */
- public void alignRealHotseatWithTaskbar() { }
-
- protected void onCreate() { }
-
- protected void onDestroy() { }
-
- protected boolean isTaskbarTouchable() {
- return true;
- }
-
- protected void onImeVisible(TaskbarContainerView container, boolean isVisible) {
- container.updateImeBarVisibilityAlpha(isVisible ? 1 : 0);
- }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index c6573a6..9e8013e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -15,14 +15,20 @@
*/
package com.android.launcher3.taskbar;
-import static android.view.View.MeasureSpec.EXACTLY;
-import static android.view.View.MeasureSpec.makeMeasureSpec;
+import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
+import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME;
+import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_RECENTS;
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.LayoutTransition;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.os.SystemProperties;
import android.util.AttributeSet;
import android.view.DragEvent;
import android.view.Gravity;
@@ -45,12 +51,17 @@
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.views.ActivityContext;
+import com.android.quickstep.SysUINavigationMode;
/**
* Hosts the Taskbar content such as Hotseat and Recent Apps. Drawn on top of other apps.
*/
public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconParent, Insettable {
+
+ private static final boolean ENABLE_THREE_BUTTON_TASKBAR =
+ SystemProperties.getBoolean("persist.debug.taskbar_three_button", false);
+
private final int mIconTouchSize;
private final boolean mIsRtl;
private final int mTouchSlop;
@@ -58,16 +69,17 @@
private final RectF mDelegateSlopBounds = new RectF();
private final int[] mTempOutLocation = new int[2];
- private final int mItemMarginLeftRight;
-
- private final TaskbarActivityContext mActivityContext;
-
// Initialized in TaskbarController constructor.
- private View.OnClickListener mIconClickListener;
- private View.OnLongClickListener mIconLongClickListener;
+ private TaskbarController.TaskbarViewCallbacks mControllerCallbacks;
+ // Scale on elements that aren't icons.
+ private float mNonIconScale;
+ private int mItemMarginLeftRight;
- LinearLayout mSystemButtonContainer;
- LinearLayout mHotseatIconsContainer;
+ // Initialized in init().
+ private LayoutTransition mLayoutTransition;
+ private int mHotseatStartIndex;
+ private int mHotseatEndIndex;
+ private LinearLayout mButtonRegion;
// Delegate touches to the closest view if within mIconTouchSize.
private boolean mDelegateTargeted;
@@ -79,12 +91,10 @@
// Only non-null when the corresponding Folder is open.
private @Nullable FolderIcon mLeaveBehindFolderIcon;
+ private int mNavButtonStartIndex;
/** Provider of buttons added to taskbar in 3 button nav */
private ButtonProvider mButtonProvider;
- private boolean mDisableRelayout;
- private boolean mAreHolesAllowed;
-
public TaskbarView(@NonNull Context context) {
this(context, null);
}
@@ -101,58 +111,80 @@
public TaskbarView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- mActivityContext = ActivityContext.lookupContext(context);
Resources resources = getResources();
mIconTouchSize = resources.getDimensionPixelSize(R.dimen.taskbar_icon_touch_size);
- mItemMarginLeftRight = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
-
mIsRtl = Utilities.isRtl(resources);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mSystemButtonContainer = findViewById(R.id.system_button_layout);
- mHotseatIconsContainer = findViewById(R.id.hotseat_icons_layout);
+ protected void construct(TaskbarController.TaskbarViewCallbacks taskbarViewCallbacks,
+ ButtonProvider buttonProvider) {
+ mControllerCallbacks = taskbarViewCallbacks;
+ mNonIconScale = mControllerCallbacks.getNonIconScale(this);
+ mItemMarginLeftRight = getResources().getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
+ mItemMarginLeftRight = Math.round(mItemMarginLeftRight * mNonIconScale);
+ mButtonProvider = buttonProvider;
+ mButtonProvider.setMarginLeftRight(mItemMarginLeftRight);
}
- protected void construct(OnClickListener clickListener, OnLongClickListener longClickListener,
- ButtonProvider buttonProvider) {
- mIconClickListener = clickListener;
- mIconLongClickListener = longClickListener;
- mButtonProvider = buttonProvider;
-
- if (mActivityContext.canShowNavButtons()) {
+ protected void init(int numHotseatIcons, SysUINavigationMode.Mode newMode) {
+ // TODO: check if buttons on left
+ if (newMode == SysUINavigationMode.Mode.THREE_BUTTONS && ENABLE_THREE_BUTTON_TASKBAR) {
+ // 3 button
+ mNavButtonStartIndex = 0;
createNavButtons();
} else {
- mSystemButtonContainer.setVisibility(GONE);
+ mNavButtonStartIndex = -1;
+ removeNavButtons();
}
- int numHotseatIcons = mActivityContext.getDeviceProfile().numShownHotseatIcons;
+ mHotseatStartIndex = mNavButtonStartIndex + 1;
+ mHotseatEndIndex = mHotseatStartIndex + numHotseatIcons - 1;
updateHotseatItems(new ItemInfo[numHotseatIcons]);
+
+ mLayoutTransition = new LayoutTransition();
+ addUpdateListenerForAllLayoutTransitions(() -> {
+ if (getLayoutTransition() == mLayoutTransition) {
+ mControllerCallbacks.onItemPositionsChanged(this);
+ }
+ });
+ setLayoutTransition(mLayoutTransition);
}
- /**
- * Enables/disables empty icons in taskbar so that the layout matches with Launcher
- */
- public void setHolesAllowedInLayout(boolean areHolesAllowed) {
- if (mAreHolesAllowed != areHolesAllowed) {
- mAreHolesAllowed = areHolesAllowed;
- updateHotseatItemsVisibility();
- // TODO: Add animation
+ private void addUpdateListenerForAllLayoutTransitions(Runnable onUpdate) {
+ addUpdateListenerForLayoutTransition(LayoutTransition.CHANGE_APPEARING, onUpdate);
+ addUpdateListenerForLayoutTransition(LayoutTransition.CHANGE_DISAPPEARING, onUpdate);
+ addUpdateListenerForLayoutTransition(LayoutTransition.CHANGING, onUpdate);
+ addUpdateListenerForLayoutTransition(LayoutTransition.APPEARING, onUpdate);
+ addUpdateListenerForLayoutTransition(LayoutTransition.DISAPPEARING, onUpdate);
+ }
+
+ private void addUpdateListenerForLayoutTransition(int transitionType, Runnable onUpdate) {
+ Animator anim = mLayoutTransition.getAnimator(transitionType);
+ if (anim instanceof ValueAnimator) {
+ ((ValueAnimator) anim).addUpdateListener(valueAnimator -> onUpdate.run());
+ } else {
+ AnimatorSet animSet = new AnimatorSet();
+ ValueAnimator updateAnim = ValueAnimator.ofFloat(0, 1);
+ updateAnim.addUpdateListener(valueAnimator -> onUpdate.run());
+ animSet.playTogether(anim, updateAnim);
+ mLayoutTransition.setAnimator(transitionType, animSet);
}
}
- private void setHolesAllowedInLayoutNoAnimation(boolean areHolesAllowed) {
- if (mAreHolesAllowed != areHolesAllowed) {
- mAreHolesAllowed = areHolesAllowed;
- updateHotseatItemsVisibility();
- onMeasure(makeMeasureSpec(getMeasuredWidth(), EXACTLY),
- makeMeasureSpec(getMeasuredHeight(), EXACTLY));
- onLayout(false, getLeft(), getTop(), getRight(), getBottom());
- }
+ protected void cleanup() {
+ endAllLayoutTransitionAnimators();
+ setLayoutTransition(null);
+ removeAllViews();
+ }
+
+ private void endAllLayoutTransitionAnimators() {
+ mLayoutTransition.getAnimator(LayoutTransition.CHANGE_APPEARING).end();
+ mLayoutTransition.getAnimator(LayoutTransition.CHANGE_DISAPPEARING).end();
+ mLayoutTransition.getAnimator(LayoutTransition.CHANGING).end();
+ mLayoutTransition.getAnimator(LayoutTransition.APPEARING).end();
+ mLayoutTransition.getAnimator(LayoutTransition.DISAPPEARING).end();
}
/**
@@ -160,9 +192,10 @@
*/
protected void updateHotseatItems(ItemInfo[] hotseatItemInfos) {
for (int i = 0; i < hotseatItemInfos.length; i++) {
- ItemInfo hotseatItemInfo = hotseatItemInfos[
- !mIsRtl ? i : hotseatItemInfos.length - i - 1];
- View hotseatView = mHotseatIconsContainer.getChildAt(i);
+ ItemInfo hotseatItemInfo = hotseatItemInfos[!mIsRtl ? i
+ : hotseatItemInfos.length - i - 1];
+ int hotseatIndex = mHotseatStartIndex + i;
+ View hotseatView = getChildAt(hotseatIndex);
// Replace any Hotseat views with the appropriate type if it's not already that type.
final int expectedLayoutResId;
@@ -180,23 +213,23 @@
} else {
expectedLayoutResId = R.layout.taskbar_app_icon;
}
- if (hotseatView == null
- || hotseatView.getSourceLayoutResId() != expectedLayoutResId
+ if (hotseatView == null || hotseatView.getSourceLayoutResId() != expectedLayoutResId
|| needsReinflate) {
- mHotseatIconsContainer.removeView(hotseatView);
+ removeView(hotseatView);
+ ActivityContext activityContext = getActivityContext();
if (isFolder) {
FolderInfo folderInfo = (FolderInfo) hotseatItemInfo;
FolderIcon folderIcon = FolderIcon.inflateFolderAndIcon(expectedLayoutResId,
- mActivityContext, this, folderInfo);
+ getActivityContext(), this, folderInfo);
folderIcon.setTextVisible(false);
hotseatView = folderIcon;
} else {
hotseatView = inflate(expectedLayoutResId);
}
- int iconSize = mActivityContext.getDeviceProfile().iconSizePx;
+ int iconSize = activityContext.getDeviceProfile().iconSizePx;
LayoutParams lp = new LayoutParams(iconSize, iconSize);
lp.setMargins(mItemMarginLeftRight, 0, mItemMarginLeftRight, 0);
- mHotseatIconsContainer.addView(hotseatView, i, lp);
+ addView(hotseatView, hotseatIndex, lp);
}
// Apply the Hotseat ItemInfos, or hide the view if there is none for a given index.
@@ -204,11 +237,13 @@
&& hotseatItemInfo instanceof WorkspaceItemInfo) {
((BubbleTextView) hotseatView).applyFromWorkspaceItem(
(WorkspaceItemInfo) hotseatItemInfo);
- hotseatView.setOnClickListener(mIconClickListener);
- hotseatView.setOnLongClickListener(mIconLongClickListener);
+ hotseatView.setOnClickListener(mControllerCallbacks.getItemOnClickListener());
+ hotseatView.setOnLongClickListener(
+ mControllerCallbacks.getItemOnLongClickListener());
} else if (isFolder) {
- hotseatView.setOnClickListener(mIconClickListener);
- hotseatView.setOnLongClickListener(mIconLongClickListener);
+ hotseatView.setOnClickListener(mControllerCallbacks.getItemOnClickListener());
+ hotseatView.setOnLongClickListener(
+ mControllerCallbacks.getItemOnLongClickListener());
} else {
hotseatView.setOnClickListener(null);
hotseatView.setOnLongClickListener(null);
@@ -219,14 +254,24 @@
}
protected void updateHotseatItemsVisibility() {
- for (int i = mHotseatIconsContainer.getChildCount() - 1; i >= 0; i--) {
- updateHotseatItemVisibility(mHotseatIconsContainer.getChildAt(i));
+ for (int i = mHotseatStartIndex; i <= mHotseatEndIndex; i++) {
+ updateHotseatItemVisibility(getChildAt(i));
}
}
private void updateHotseatItemVisibility(View hotseatView) {
- hotseatView.setVisibility(
- hotseatView.getTag() != null ? VISIBLE : (mAreHolesAllowed ? INVISIBLE : GONE));
+ if (hotseatView.getTag() != null) {
+ hotseatView.setVisibility(VISIBLE);
+ } else {
+ int oldVisibility = hotseatView.getVisibility();
+ int newVisibility = mControllerCallbacks.getEmptyHotseatViewVisibility(this);
+ hotseatView.setVisibility(newVisibility);
+ if (oldVisibility == GONE && newVisibility != GONE) {
+ // By default, the layout transition only runs when going to VISIBLE,
+ // but we want it to run when going to GONE to INVISIBLE as well.
+ getLayoutTransition().showChild(this, hotseatView, oldVisibility);
+ }
+ }
}
@Override
@@ -333,20 +378,49 @@
return findDelegateView(xInOurCoordinates, yInOurCoorindates) != null;
}
+ private void removeNavButtons() {
+ if (mButtonRegion != null) {
+ mButtonRegion.removeAllViews();
+ removeView(mButtonRegion);
+ } // else We've never been in 3 button. Woah Scoob!
+ }
+
/**
* Add back/home/recents buttons into a single ViewGroup that will be inserted at
* {@param navButtonStartIndex}
*/
private void createNavButtons() {
+ ActivityContext context = getActivityContext();
+ if (mButtonRegion == null) {
+ mButtonRegion = new LinearLayout(getContext());
+ } else {
+ mButtonRegion.removeAllViews();
+ }
+ mButtonRegion.setVisibility(VISIBLE);
+
LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(
- mActivityContext.getDeviceProfile().iconSizePx,
- mActivityContext.getDeviceProfile().iconSizePx
+ context.getDeviceProfile().iconSizePx,
+ context.getDeviceProfile().iconSizePx
);
buttonParams.gravity = Gravity.CENTER;
- mSystemButtonContainer.addView(mButtonProvider.getBack(), buttonParams);
- mSystemButtonContainer.addView(mButtonProvider.getHome(), buttonParams);
- mSystemButtonContainer.addView(mButtonProvider.getRecents(), buttonParams);
+ View backButton = mButtonProvider.getBack();
+ backButton.setOnClickListener(view -> mControllerCallbacks.onNavigationButtonClick(
+ BUTTON_BACK));
+ mButtonRegion.addView(backButton, buttonParams);
+
+ // Home button
+ View homeButton = mButtonProvider.getHome();
+ homeButton.setOnClickListener(view -> mControllerCallbacks.onNavigationButtonClick(
+ BUTTON_HOME));
+ mButtonRegion.addView(homeButton, buttonParams);
+
+ View recentsButton = mButtonProvider.getRecents();
+ recentsButton.setOnClickListener(view -> mControllerCallbacks.onNavigationButtonClick(
+ BUTTON_RECENTS));
+ mButtonRegion.addView(recentsButton, buttonParams);
+
+ addView(mButtonRegion, mNavButtonStartIndex);
}
@Override
@@ -354,7 +428,7 @@
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
mIsDraggingItem = true;
- AbstractFloatingView.closeAllOpenViews(mActivityContext);
+ AbstractFloatingView.closeAllOpenViews(getActivityContext());
return true;
case DragEvent.ACTION_DRAG_ENDED:
mIsDraggingItem = false;
@@ -371,26 +445,26 @@
* @return The bounding box of where the hotseat elements are relative to this TaskbarView.
*/
protected RectF getHotseatBounds() {
- RectF result;
- mDisableRelayout = true;
- boolean wereHolesAllowed = mAreHolesAllowed;
- setHolesAllowedInLayoutNoAnimation(true);
- result = new RectF(
- mHotseatIconsContainer.getLeft(),
- mHotseatIconsContainer.getTop(),
- mHotseatIconsContainer.getRight(),
- mHotseatIconsContainer.getBottom());
- setHolesAllowedInLayoutNoAnimation(wereHolesAllowed);
- mDisableRelayout = false;
-
- return result;
- }
-
- @Override
- public void requestLayout() {
- if (!mDisableRelayout) {
- super.requestLayout();
+ View firstHotseatView = null, lastHotseatView = null;
+ for (int i = mHotseatStartIndex; i <= mHotseatEndIndex; i++) {
+ View child = getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ if (firstHotseatView == null) {
+ firstHotseatView = child;
+ }
+ lastHotseatView = child;
+ }
}
+ if (firstHotseatView == null || lastHotseatView == null) {
+ return new RectF();
+ }
+ View leftmostHotseatView = !mIsRtl ? firstHotseatView : lastHotseatView;
+ View rightmostHotseatView = !mIsRtl ? lastHotseatView : firstHotseatView;
+ return new RectF(
+ leftmostHotseatView.getLeft() - mItemMarginLeftRight,
+ leftmostHotseatView.getTop(),
+ rightmostHotseatView.getRight() + mItemMarginLeftRight,
+ rightmostHotseatView.getBottom());
}
// FolderIconParent implemented methods.
@@ -421,7 +495,7 @@
}
private View inflate(@LayoutRes int layoutResId) {
- return mActivityContext.getLayoutInflater().inflate(layoutResId, this, false);
+ return getActivityContext().getLayoutInflater().inflate(layoutResId, this, false);
}
@Override
@@ -429,11 +503,7 @@
// Ignore, we just implement Insettable to draw behind system insets.
}
- public void setIconsVisibility(boolean isVisible) {
- mHotseatIconsContainer.setVisibility(isVisible ? VISIBLE : INVISIBLE);
- }
-
- public boolean areIconsVisible() {
- return mHotseatIconsContainer.getVisibility() == VISIBLE;
+ private <T extends Context & ActivityContext> T getActivityContext() {
+ return ActivityContext.lookupContext(getContext());
}
}
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 86bf119..f5ddd0e 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -52,6 +52,7 @@
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.taskbar.TaskbarController;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.views.ScrimView;
@@ -122,6 +123,11 @@
return null;
}
+ @Nullable
+ public TaskbarController getTaskbarController() {
+ return null;
+ }
+
public final boolean isResumed() {
ACTIVITY_TYPE activity = getCreatedActivity();
return activity != null && activity.hasBeenResumed();
@@ -362,6 +368,13 @@
protected abstract int getOverviewScrimColorForState(ACTIVITY_TYPE activity, STATE_TYPE state);
/**
+ * See {@link com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags}
+ * @param systemUiStateFlags The latest SystemUiStateFlags
+ */
+ public void onSystemUiFlagsChanged(int systemUiStateFlags) {
+ }
+
+ /**
* Returns the expected STATE_TYPE from the provided GestureEndTarget.
*/
public abstract STATE_TYPE stateFromGestureEndTarget(GestureState.GestureEndTarget endTarget);
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index ff69180..5217c3b 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -163,7 +164,8 @@
}
@Nullable
- private TaskbarController getTaskbarController() {
+ @Override
+ public TaskbarController getTaskbarController() {
BaseQuickstepLauncher launcher = getCreatedActivity();
if (launcher == null) {
return null;
@@ -299,6 +301,16 @@
}
@Override
+ public void onSystemUiFlagsChanged(int systemUiStateFlags) {
+ TaskbarController taskbarController = getTaskbarController();
+ if (taskbarController == null) {
+ return;
+ }
+ boolean isImeVisible = (systemUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0;
+ taskbarController.setIsImeVisible(isImeVisible);
+ }
+
+ @Override
public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
TaskbarController taskbarController = getTaskbarController();
if (taskbarController == null) {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index d95f7b7..edc7a3c 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -52,6 +52,7 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Log;
@@ -74,7 +75,6 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.statemanager.StatefulActivity;
-import com.android.launcher3.taskbar.TaskbarManager;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.tracing.LauncherTraceProto;
@@ -147,9 +147,21 @@
private OverscrollPlugin mOverscrollPlugin;
/**
- * Local IOverviewProxy implementation with some methods for local components
+ * Extension of OverviewProxy aidl interface without needing to modify the actual interface.
+ * This is for methods that need only need local access and not intended to make IPC calls.
*/
- public class TISBinder extends IOverviewProxy.Stub {
+ public abstract static class TISBinder extends IOverviewProxy.Stub {
+ public abstract void setTaskbarOverviewProxyDelegate(
+ @Nullable TaskbarOverviewProxyDelegate i);
+ }
+
+
+ private final TISBinder mMyBinder = new TISBinder() {
+
+ public void setTaskbarOverviewProxyDelegate(
+ @Nullable TaskbarOverviewProxyDelegate delegate) {
+ mTaskbarOverviewProxyDelegate = delegate;
+ }
@BinderThread
public void onInitialize(Bundle bundle) {
@@ -262,24 +274,40 @@
@Override
public void onImeWindowStatusChanged(int displayId, IBinder token, int vis,
- int backDisposition, boolean showImeSwitcher) {
- MAIN_EXECUTOR.execute(() -> mTaskbarManager.updateImeStatus(
- displayId, vis, backDisposition, showImeSwitcher));
+ int backDisposition, boolean showImeSwitcher) throws RemoteException {
+ if (mTaskbarOverviewProxyDelegate == null) {
+ return;
+ }
+ MAIN_EXECUTOR.execute(() -> {
+ if (mTaskbarOverviewProxyDelegate == null) {
+ return;
+ }
+ mTaskbarOverviewProxyDelegate
+ .updateImeStatus(displayId, vis, backDisposition, showImeSwitcher);
+ });
}
+ };
- public TaskbarManager getTaskbarManager() {
- return mTaskbarManager;
- }
+ public interface TaskbarOverviewProxyDelegate {
+ void updateImeStatus(int displayId, int vis, int backDisposition,
+ boolean showImeSwitcher);
}
private static boolean sConnected = false;
+ private static TouchInteractionService sInstance;
private static boolean sIsInitialized = false;
private RotationTouchHelper mRotationTouchHelper;
+ @Nullable
+ private TaskbarOverviewProxyDelegate mTaskbarOverviewProxyDelegate;
public static boolean isConnected() {
return sConnected;
}
+ @Nullable
+ public static TouchInteractionService getInstance() {
+ return sInstance;
+ }
public static boolean isInitialized() {
return sIsInitialized;
@@ -308,7 +336,9 @@
private DisplayManager mDisplayManager;
- private TaskbarManager mTaskbarManager;
+ public TouchInteractionService() {
+ sInstance = this;
+ }
@Override
public void onCreate() {
@@ -318,14 +348,13 @@
mMainChoreographer = Choreographer.getInstance();
mAM = ActivityManagerWrapper.getInstance();
mDeviceState = new RecentsAnimationDeviceState(this, true);
- mDisplayManager = getSystemService(DisplayManager.class);
- mTaskbarManager = new TaskbarManager(this);
-
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
mDeviceState.addOneHandedModeChangedCallback(this::onOneHandedModeOverlayChanged);
mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
ProtoTracer.INSTANCE.get(this).add(this);
+ mDisplayManager = getSystemService(DisplayManager.class);
+
sConnected = true;
}
@@ -439,7 +468,8 @@
int systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
mOverviewComponentObserver.onSystemUiStateChanged();
- mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
+ mOverviewComponentObserver.getActivityInterface().onSystemUiFlagsChanged(
+ systemUiStateFlags);
if ((lastSysUIFlags & SYSUI_STATE_TRACING_ENABLED) !=
(systemUiStateFlags & SYSUI_STATE_TRACING_ENABLED)) {
@@ -482,7 +512,6 @@
getSystemService(AccessibilityManager.class)
.unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
- mTaskbarManager.destroy();
sConnected = false;
super.onDestroy();
}
@@ -490,7 +519,7 @@
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "Touch service connected: user=" + getUserId());
- return new TISBinder();
+ return mMyBinder;
}
private void onInputEvent(InputEvent ev) {
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 49aec93..d430028 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -116,7 +116,7 @@
addStaggeredAnimationForView(child, lp.cellY + 1, totalRows);
}
} else {
- final int hotseatRow, qsbRow;
+ final int hotseatRow, qsbRow, taskbarRow;
if (grid.isTaskbarPresent) {
qsbRow = grid.inv.numRows + 1;
hotseatRow = grid.inv.numRows + 2;
@@ -124,12 +124,16 @@
hotseatRow = grid.inv.numRows + 1;
qsbRow = grid.inv.numRows + 2;
}
+ // Taskbar and hotseat overlap.
+ taskbarRow = hotseatRow;
+
for (int i = hotseatIcons.getChildCount() - 1; i >= 0; i--) {
View child = hotseatIcons.getChildAt(i);
addStaggeredAnimationForView(child, hotseatRow, totalRows);
}
addStaggeredAnimationForView(hotseat.getQsb(), qsbRow, totalRows);
+ addStaggeredAnimationForView(hotseat.getTaskbarView(), taskbarRow, totalRows);
}
mAnimators.addListener(new AnimatorListenerAdapter() {
diff --git a/res/layout/taskbar_view.xml b/res/layout/taskbar_view.xml
new file mode 100644
index 0000000..96ae43d
--- /dev/null
+++ b/res/layout/taskbar_view.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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.
+-->
+<Space
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:visibility="gone" />
\ No newline at end of file
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 322c6ee..3d044d6 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -447,6 +447,10 @@
* @param canvas The canvas to draw to.
*/
protected void drawDotIfNecessary(Canvas canvas) {
+ if (mActivity instanceof Launcher && ((Launcher) mActivity).isViewInTaskbar(this)) {
+ // TODO: support notification dots in Taskbar
+ return;
+ }
if (!mForceHideDot && (hasDot() || mDotParams.scale > 0)) {
getIconBounds(mDotParams.iconBounds);
Utilities.scaleRectAboutCenter(mDotParams.iconBounds,
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index ff380ce..b2a9e75 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -49,6 +49,7 @@
private final View mQsb;
private final int mQsbHeight;
+ private final View mTaskbarView;
private final int mTaskbarViewHeight;
public Hotseat(Context context) {
@@ -66,7 +67,10 @@
mQsbHeight = mQsb.getLayoutParams().height;
addView(mQsb);
- mTaskbarViewHeight = context.getResources().getDimensionPixelSize(R.dimen.taskbar_size);
+ mTaskbarView = LayoutInflater.from(context).inflate(R.layout.taskbar_view, this, false);
+ mTaskbarViewHeight = mTaskbarView.getLayoutParams().height;
+ // We want taskbar in the back so its background applies to Hotseat as well.
+ addView(mTaskbarView, 0);
}
/**
@@ -183,6 +187,8 @@
int width = getShortcutsAndWidgets().getMeasuredWidth();
mQsb.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mQsbHeight, MeasureSpec.EXACTLY));
+ mTaskbarView.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(mTaskbarViewHeight, MeasureSpec.EXACTLY));
}
@Override
@@ -196,6 +202,13 @@
int bottom = b - t - getQsbOffsetY();
int top = bottom - mQsbHeight;
mQsb.layout(left, top, right, bottom);
+
+ int taskbarWidth = mTaskbarView.getMeasuredWidth();
+ left = (r - l - taskbarWidth) / 2;
+ right = left + taskbarWidth;
+ bottom = b - t - getTaskbarOffsetY();
+ top = bottom - mTaskbarViewHeight;
+ mTaskbarView.layout(left, top, right, bottom);
}
/**
@@ -231,4 +244,10 @@
return mQsb;
}
+ /**
+ * Returns the Taskbar inside hotseat
+ */
+ public View getTaskbarView() {
+ return mTaskbarView;
+ }
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 8889e60..cf90216 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1942,6 +1942,13 @@
@Override
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
+ if (isViewInTaskbar(v)) {
+ // Start the activity without the hacky workarounds below, which assume the View was
+ // clicked when Launcher was resumed and will be hidden until Launcher is re-resumed
+ // (this isn't the case for Taskbar).
+ return super.startActivitySafely(v, intent, item);
+ }
+
if (!hasBeenResumed()) {
// Workaround an issue where the WM launch animation is clobbered when finishing the
// recents animation into launcher. Defer launching the activity until Launcher is
@@ -2853,6 +2860,13 @@
.start();
}
+ /**
+ * @return Whether the View is in the same window as the Taskbar window.
+ */
+ public boolean isViewInTaskbar(View v) {
+ return false;
+ }
+
public boolean supportsAdaptiveIconAnimation(View clickedView) {
return false;
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 2884fba..7ae729a 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -324,17 +324,15 @@
}
public static void scaleRectFAboutCenter(RectF r, float scale) {
- scaleRectFAboutPivot(r, scale, r.centerX(), r.centerY());
- }
-
- public static void scaleRectFAboutPivot(RectF r, float scale, float px, float py) {
if (scale != 1.0f) {
- r.offset(-px, -py);
+ float cx = r.centerX();
+ float cy = r.centerY();
+ r.offset(-cx, -cy);
r.left = r.left * scale;
r.top = r.top * scale ;
r.right = r.right * scale;
r.bottom = r.bottom * scale;
- r.offset(px, py);
+ r.offset(cx, cy);
}
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index b5dcd3a..ce7dc07 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -27,7 +27,6 @@
import android.app.AlertDialog;
import android.app.PendingIntent;
-import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.LauncherApps;
@@ -195,43 +194,36 @@
}
/**
- * Handles clicking on a disabled shortcut
- */
- public static void handleDisabledItemClicked(WorkspaceItemInfo shortcut, Context context) {
- final int disabledFlags = shortcut.runtimeStatusFlags
- & WorkspaceItemInfo.FLAG_DISABLED_MASK;
- if ((disabledFlags
- & ~FLAG_DISABLED_SUSPENDED
- & ~FLAG_DISABLED_QUIET_USER) == 0) {
- // If the app is only disabled because of the above flags, launch activity anyway.
- // Framework will tell the user why the app is suspended.
- } else {
- if (!TextUtils.isEmpty(shortcut.disabledMessage)) {
- // Use a message specific to this shortcut, if it has one.
- Toast.makeText(context, shortcut.disabledMessage, Toast.LENGTH_SHORT).show();
- return;
- }
- // Otherwise just use a generic error message.
- int error = R.string.activity_not_available;
- if ((shortcut.runtimeStatusFlags & FLAG_DISABLED_SAFEMODE) != 0) {
- error = R.string.safemode_shortcut_error;
- } else if ((shortcut.runtimeStatusFlags & FLAG_DISABLED_BY_PUBLISHER) != 0
- || (shortcut.runtimeStatusFlags & FLAG_DISABLED_LOCKED_USER) != 0) {
- error = R.string.shortcut_not_available;
- }
- Toast.makeText(context, error, Toast.LENGTH_SHORT).show();
- }
- }
-
- /**
* Event handler for an app shortcut click.
*
* @param v The view that was clicked. Must be a tagged with a {@link WorkspaceItemInfo}.
*/
public static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher) {
if (shortcut.isDisabled()) {
- handleDisabledItemClicked(shortcut, launcher);
- return;
+ final int disabledFlags = shortcut.runtimeStatusFlags
+ & WorkspaceItemInfo.FLAG_DISABLED_MASK;
+ if ((disabledFlags &
+ ~FLAG_DISABLED_SUSPENDED &
+ ~FLAG_DISABLED_QUIET_USER) == 0) {
+ // If the app is only disabled because of the above flags, launch activity anyway.
+ // Framework will tell the user why the app is suspended.
+ } else {
+ if (!TextUtils.isEmpty(shortcut.disabledMessage)) {
+ // Use a message specific to this shortcut, if it has one.
+ Toast.makeText(launcher, shortcut.disabledMessage, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ // Otherwise just use a generic error message.
+ int error = R.string.activity_not_available;
+ if ((shortcut.runtimeStatusFlags & FLAG_DISABLED_SAFEMODE) != 0) {
+ error = R.string.safemode_shortcut_error;
+ } else if ((shortcut.runtimeStatusFlags & FLAG_DISABLED_BY_PUBLISHER) != 0 ||
+ (shortcut.runtimeStatusFlags & FLAG_DISABLED_LOCKED_USER) != 0) {
+ error = R.string.shortcut_not_available;
+ }
+ Toast.makeText(launcher, error, Toast.LENGTH_SHORT).show();
+ return;
+ }
}
// Check for abandoned promise