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.R; 33 import com.android.launcher3.allapps.AllAppsContainerView; 34 import com.android.launcher3.model.data.ItemInfo; 35 import com.android.launcher3.popup.PopupContainerWithArrow; 36 import com.android.launcher3.util.ShortcutUtil; 37 import com.android.launcher3.util.TouchController; 38 import com.android.launcher3.views.BaseDragLayer; 39 40 import java.util.Arrays; 41 import java.util.Collections; 42 43 /** 44 * DragLayer for Secondary launcher 45 */ 46 public class SecondaryDragLayer extends BaseDragLayer<SecondaryDisplayLauncher> { 47 48 private View mAllAppsButton; 49 private AllAppsContainerView mAppsView; 50 51 private GridView mWorkspace; 52 private PinnedAppsAdapter mPinnedAppsAdapter; 53 SecondaryDragLayer(Context context, AttributeSet attrs)54 public SecondaryDragLayer(Context context, AttributeSet attrs) { 55 super(context, attrs, 1 /* alphaChannelCount */); 56 recreateControllers(); 57 } 58 59 @Override recreateControllers()60 public void recreateControllers() { 61 mControllers = new TouchController[] {new CloseAllAppsTouchController()}; 62 } 63 64 /** 65 * {@inheritDoc} 66 */ 67 @Override onFinishInflate()68 protected void onFinishInflate() { 69 super.onFinishInflate(); 70 mAllAppsButton = findViewById(R.id.all_apps_button); 71 72 mAppsView = findViewById(R.id.apps_view); 73 mAppsView.setOnIconLongClickListener(this::onIconLongClicked); 74 75 // Setup workspace 76 mWorkspace = findViewById(R.id.workspace_grid); 77 mPinnedAppsAdapter = new PinnedAppsAdapter(mActivity, mAppsView.getAppsStore(), 78 this::onIconLongClicked); 79 mWorkspace.setAdapter(mPinnedAppsAdapter); 80 mWorkspace.setNumColumns(mActivity.getDeviceProfile().inv.numColumns); 81 } 82 83 /** 84 * {@inheritDoc} 85 */ 86 @Override onAttachedToWindow()87 protected void onAttachedToWindow() { 88 super.onAttachedToWindow(); 89 mPinnedAppsAdapter.init(); 90 } 91 92 /** 93 * {@inheritDoc} 94 */ 95 @Override onDetachedFromWindow()96 protected void onDetachedFromWindow() { 97 super.onDetachedFromWindow(); 98 mPinnedAppsAdapter.destroy(); 99 } 100 101 /** 102 * {@inheritDoc} 103 */ 104 @Override onMeasure(int widthMeasureSpec, int heightMeasureSpec)105 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 106 int width = MeasureSpec.getSize(widthMeasureSpec); 107 int height = MeasureSpec.getSize(heightMeasureSpec); 108 setMeasuredDimension(width, height); 109 110 DeviceProfile grid = mActivity.getDeviceProfile(); 111 int count = getChildCount(); 112 for (int i = 0; i < count; i++) { 113 final View child = getChildAt(i); 114 if (child == mAppsView) { 115 int padding = 2 * (grid.desiredWorkspaceLeftRightMarginPx 116 + grid.cellLayoutPaddingLeftRightPx); 117 118 int maxWidth = grid.allAppsCellWidthPx * grid.numShownAllAppsColumns + padding; 119 int appsWidth = Math.min(width, maxWidth); 120 121 int maxHeight = grid.allAppsCellHeightPx * grid.numShownAllAppsColumns + padding; 122 int appsHeight = Math.min(height, maxHeight); 123 124 mAppsView.measure( 125 makeMeasureSpec(appsWidth, EXACTLY), makeMeasureSpec(appsHeight, EXACTLY)); 126 127 } else if (child == mAllAppsButton) { 128 int appsButtonSpec = makeMeasureSpec(grid.iconSizePx, EXACTLY); 129 mAllAppsButton.measure(appsButtonSpec, appsButtonSpec); 130 131 } else if (child == mWorkspace) { 132 measureChildWithMargins(mWorkspace, widthMeasureSpec, 0, heightMeasureSpec, 133 grid.iconSizePx + grid.edgeMarginPx); 134 135 } else { 136 measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); 137 } 138 } 139 } 140 141 private class CloseAllAppsTouchController implements TouchController { 142 143 @Override onControllerTouchEvent(MotionEvent ev)144 public boolean onControllerTouchEvent(MotionEvent ev) { 145 return false; 146 } 147 148 @Override onControllerInterceptTouchEvent(MotionEvent ev)149 public boolean onControllerInterceptTouchEvent(MotionEvent ev) { 150 if (!mActivity.isAppDrawerShown()) { 151 return false; 152 } 153 154 if (AbstractFloatingView.getTopOpenView(mActivity) != null) { 155 return false; 156 } 157 158 if (ev.getAction() == MotionEvent.ACTION_DOWN 159 && !isEventOverView(mActivity.getAppsView(), ev)) { 160 mActivity.showAppDrawer(false); 161 return true; 162 } 163 return false; 164 } 165 } 166 onIconLongClicked(View v)167 private boolean onIconLongClicked(View v) { 168 if (!(v instanceof BubbleTextView)) { 169 return false; 170 } 171 if (PopupContainerWithArrow.getOpen(mActivity) != null) { 172 // There is already an items container open, so don't open this one. 173 v.clearFocus(); 174 return false; 175 } 176 ItemInfo item = (ItemInfo) v.getTag(); 177 if (!ShortcutUtil.supportsShortcuts(item)) { 178 return false; 179 } 180 final PopupContainerWithArrow container = 181 (PopupContainerWithArrow) mActivity.getLayoutInflater().inflate( 182 R.layout.popup_container, mActivity.getDragLayer(), false); 183 184 container.populateAndShow((BubbleTextView) v, 185 mActivity.getPopupDataProvider().getShortcutCountForItem(item), 186 Collections.emptyList(), 187 Arrays.asList(mPinnedAppsAdapter.getSystemShortcut(item), 188 APP_INFO.getShortcut(mActivity, item))); 189 v.getParent().requestDisallowInterceptTouchEvent(true); 190 return true; 191 } 192 } 193