1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.launcher3.secondarydisplay; 17 18 import static android.view.View.MeasureSpec.EXACTLY; 19 import static android.view.View.MeasureSpec.makeMeasureSpec; 20 21 import static com.android.launcher3.popup.SystemShortcut.APP_INFO; 22 23 import android.content.Context; 24 import android.util.AttributeSet; 25 import android.view.MotionEvent; 26 import android.view.View; 27 import android.widget.GridView; 28 29 import com.android.launcher3.AbstractFloatingView; 30 import com.android.launcher3.BubbleTextView; 31 import com.android.launcher3.DeviceProfile; 32 import com.android.launcher3.InvariantDeviceProfile; 33 import com.android.launcher3.R; 34 import com.android.launcher3.allapps.AllAppsContainerView; 35 import com.android.launcher3.model.data.ItemInfo; 36 import com.android.launcher3.popup.PopupContainerWithArrow; 37 import com.android.launcher3.util.ShortcutUtil; 38 import com.android.launcher3.util.TouchController; 39 import com.android.launcher3.views.BaseDragLayer; 40 41 import java.util.Arrays; 42 import java.util.Collections; 43 44 /** 45 * DragLayer for Secondary launcher 46 */ 47 public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher> { 48 49 private View mAllAppsButton; 50 private AllAppsContainerView mAppsView; 51 52 private GridView mWorkspace; 53 private PinnedAppsAdapter mPinnedAppsAdapter; 54 SecondaryDragLayer(Context context, AttributeSet attrs)55 public SecondaryDragLayer(Context context, AttributeSet attrs) { 56 super(context, attrs, 1 /* alphaChannelCount */); 57 recreateControllers(); 58 } 59 60 @Override recreateControllers()61 public void recreateControllers() { 62 mControllers = new TouchController[] {new CloseAllAppsTouchController()}; 63 } 64 65 /** 66 * {@inheritDoc} 67 */ 68 @Override onFinishInflate()69 protected void onFinishInflate() { 70 super.onFinishInflate(); 71 mAllAppsButton = findViewById(R.id.all_apps_button); 72 73 mAppsView = findViewById(R.id.apps_view); 74 mAppsView.setOnIconLongClickListener(this::onIconLongClicked); 75 76 // Setup workspace 77 mWorkspace = findViewById(R.id.workspace_grid); 78 mPinnedAppsAdapter = new PinnedAppsAdapter(mActivity, mAppsView.getAppsStore(), 79 this::onIconLongClicked); 80 mWorkspace.setAdapter(mPinnedAppsAdapter); 81 mWorkspace.setNumColumns(mActivity.getDeviceProfile().inv.numColumns); 82 } 83 84 /** 85 * {@inheritDoc} 86 */ 87 @Override onAttachedToWindow()88 protected void onAttachedToWindow() { 89 super.onAttachedToWindow(); 90 mPinnedAppsAdapter.init(); 91 } 92 93 /** 94 * {@inheritDoc} 95 */ 96 @Override onDetachedFromWindow()97 protected void onDetachedFromWindow() { 98 super.onDetachedFromWindow(); 99 mPinnedAppsAdapter.destroy(); 100 } 101 102 /** 103 * {@inheritDoc} 104 */ 105 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)106 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 107 int width = MeasureSpec.getSize(widthMeasureSpec); 108 int height = MeasureSpec.getSize(heightMeasureSpec); 109 setMeasuredDimension(width, height); 110 111 DeviceProfile grid = mActivity.getDeviceProfile(); 112 InvariantDeviceProfile idp = grid.inv; 113 114 int count = getChildCount(); 115 for (int i = 0; i < count; i++) { 116 final View child = getChildAt(i); 117 if (child == mAppsView) { 118 int padding = 2 * (grid.desiredWorkspaceLeftRightMarginPx 119 + grid.cellLayoutPaddingLeftRightPx); 120 121 int maxWidth = grid.allAppsCellWidthPx * idp.numAllAppsColumns + padding; 122 int appsWidth = Math.min(width, maxWidth); 123 124 int maxHeight = grid.allAppsCellHeightPx * idp.numAllAppsColumns + padding; 125 int appsHeight = Math.min(height, maxHeight); 126 127 mAppsView.measure( 128 makeMeasureSpec(appsWidth, EXACTLY), makeMeasureSpec(appsHeight, EXACTLY)); 129 130 } else if (child == mAllAppsButton) { 131 int appsButtonSpec = makeMeasureSpec(grid.iconSizePx, EXACTLY); 132 mAllAppsButton.measure(appsButtonSpec, appsButtonSpec); 133 134 } else if (child == mWorkspace) { 135 measureChildWithMargins(mWorkspace, widthMeasureSpec, 0, heightMeasureSpec, 136 grid.iconSizePx + grid.edgeMarginPx); 137 138 } else { 139 measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); 140 } 141 } 142 } 143 144 private class CloseAllAppsTouchController implements TouchController { 145 146 @Override onControllerTouchEvent(MotionEvent ev)147 public boolean onControllerTouchEvent(MotionEvent ev) { 148 return false; 149 } 150 151 @Override onControllerInterceptTouchEvent(MotionEvent ev)152 public boolean onControllerInterceptTouchEvent(MotionEvent ev) { 153 if (!mActivity.isAppDrawerShown()) { 154 return false; 155 } 156 157 if (AbstractFloatingView.getTopOpenView(mActivity) != null) { 158 return false; 159 } 160 161 if (ev.getAction() == MotionEvent.ACTION_DOWN 162 && !isEventOverView(mActivity.getAppsView(), ev)) { 163 mActivity.showAppDrawer(false); 164 return true; 165 } 166 return false; 167 } 168 } 169 onIconLongClicked(View v)170 private boolean onIconLongClicked(View v) { 171 if (!(v instanceof BubbleTextView)) { 172 return false; 173 } 174 if (PopupContainerWithArrow.getOpen(mActivity) != null) { 175 // There is already an items container open, so don't open this one. 176 v.clearFocus(); 177 return false; 178 } 179 ItemInfo item = (ItemInfo) v.getTag(); 180 if (!ShortcutUtil.supportsShortcuts(item)) { 181 return false; 182 } 183 final PopupContainerWithArrow container = 184 (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate( 185 R.layout.popup_container, mActivity.getDragLayer(), false); 186 187 container.populateAndShow((BubbleTextView) v, 188 mActivity.getPopupDataProvider().getShortcutCountForItem(item), 189 Collections.emptyList(), 190 Arrays.asList(mPinnedAppsAdapter.getSystemShortcut(item), 191 APP_INFO.getShortcut(mActivity, item))); 192 v.getParent().requestDisallowInterceptTouchEvent(true); 193 return true; 194 } 195 } 196